@ticatec/uniface-element 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/dist/accordion/README.md +169 -0
  2. package/dist/accordion/README_CN.md +176 -0
  3. package/dist/action-bar/README.md +275 -0
  4. package/dist/action-bar/README_CN.md +285 -0
  5. package/dist/app-layout/README.md +374 -0
  6. package/dist/app-layout/README_CN.md +381 -0
  7. package/dist/app-top-bar/README.md +357 -0
  8. package/dist/app-top-bar/README_CN.md +365 -0
  9. package/dist/attachment-files/AttachmentFilesField.svelte +67 -1
  10. package/dist/attachment-files/AttachmentFilesField.svelte.d.ts +8 -1
  11. package/dist/base-calendar/CalendarBase.svelte +0 -3
  12. package/dist/box/README.md +385 -0
  13. package/dist/box/README_CN.md +393 -0
  14. package/dist/breadcrumbs/README.md +442 -0
  15. package/dist/breadcrumbs/README_CN.md +442 -0
  16. package/dist/button/Button.svelte +27 -7
  17. package/dist/button/Button.svelte.d.ts +3 -1
  18. package/dist/button/IconButton.svelte +26 -6
  19. package/dist/button/IconButton.svelte.d.ts +3 -1
  20. package/dist/button/IconButton_README.md +513 -0
  21. package/dist/button/IconButton_README_CN.md +513 -0
  22. package/dist/button/README.md +428 -0
  23. package/dist/button/README_CN.md +428 -0
  24. package/dist/button/TextButton.svelte +26 -6
  25. package/dist/button/TextButton.svelte.d.ts +3 -1
  26. package/dist/button/TextButton_README.md +571 -0
  27. package/dist/button/TextButton_README_CN.md +571 -0
  28. package/dist/card/README.md +666 -0
  29. package/dist/card/README_CN.md +666 -0
  30. package/dist/cascade-options-select/CascadeOptionSelect.svelte +43 -7
  31. package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +3 -4
  32. package/dist/cascade-options-select/README.md +663 -2
  33. package/dist/cascade-options-select/README_CN.md +664 -0
  34. package/dist/checkbox/CheckBox.svelte +20 -6
  35. package/dist/checkbox/CheckBox.svelte.d.ts +4 -2
  36. package/dist/checkbox/README.md +562 -0
  37. package/dist/checkbox/README_CN.md +727 -0
  38. package/dist/common-editor/NumberInput.svelte +39 -26
  39. package/dist/common-editor/NumberInput.svelte.d.ts +5 -1
  40. package/dist/concise-data-table/ConciseListTable.svelte +133 -36
  41. package/dist/concise-data-table/ConciseListTable.svelte.d.ts +8 -1
  42. package/dist/concise-data-table/DataCell.svelte +5 -6
  43. package/dist/concise-data-table/DataRow.svelte +22 -2
  44. package/dist/concise-data-table/DataRow.svelte.d.ts +1 -0
  45. package/dist/concise-data-table/README.md +606 -0
  46. package/dist/concise-data-table/README_CN.md +611 -0
  47. package/dist/context-menu/ContextMenu.svelte +138 -21
  48. package/dist/context-menu/ContextMenu.svelte.d.ts +5 -0
  49. package/dist/context-menu/ContextMenuItem.d.ts +20 -4
  50. package/dist/context-menu/README.md +551 -0
  51. package/dist/context-menu/README_CN.md +551 -0
  52. package/dist/criteria-field/CriteriaField.svelte +3 -5
  53. package/dist/criteria-field/README.md +532 -0
  54. package/dist/criteria-field/README_CN.md +532 -0
  55. package/dist/data-table/README.md +712 -0
  56. package/dist/data-table/README_CN.md +712 -0
  57. package/dist/date-picker/DatePicker.svelte +44 -7
  58. package/dist/date-picker/DatePicker.svelte.d.ts +3 -4
  59. package/dist/date-picker/DateTimePicker.svelte +32 -8
  60. package/dist/date-picker/DateTimePicker.svelte.d.ts +3 -4
  61. package/dist/date-picker/README.md +326 -0
  62. package/dist/date-picker/README_CN.md +316 -0
  63. package/dist/date-picker/ScrollBar.svelte +18 -8
  64. package/dist/date-picker/ScrollBar.svelte.d.ts +1 -1
  65. package/dist/date-picker/TimePanel.svelte +5 -5
  66. package/dist/date-picker/TimePanel.svelte.d.ts +1 -1
  67. package/dist/date-range/README.md +374 -0
  68. package/dist/date-range/README_CN.md +374 -0
  69. package/dist/dialog/README.md +596 -0
  70. package/dist/dialog/README_CN.md +596 -0
  71. package/dist/drawer/README.md +679 -1
  72. package/dist/drawer/README_CN.md +679 -0
  73. package/dist/group-box/group-check-box/GroupCheckBox.svelte +62 -5
  74. package/dist/group-box/group-check-box/GroupCheckBox.svelte.d.ts +7 -2
  75. package/dist/group-box/group-check-box/README.md +749 -0
  76. package/dist/group-box/group-check-box/README_CN.md +750 -0
  77. package/dist/group-box/group-radio-box/GroupRadioBox.svelte +69 -4
  78. package/dist/group-box/group-radio-box/GroupRadioBox.svelte.d.ts +8 -2
  79. package/dist/group-box/group-radio-box/README.md +920 -0
  80. package/dist/group-box/group-radio-box/README_CN.md +920 -0
  81. package/dist/image-files/README.md +1346 -0
  82. package/dist/image-files/README_CN.md +1346 -0
  83. package/dist/input-options-select/InputOptionsSelect.svelte +161 -65
  84. package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +4 -1
  85. package/dist/lib/forwardAllEvents.d.ts +3 -0
  86. package/dist/lib/forwardAllEvents.js +24 -0
  87. package/dist/list-box/README.md +579 -0
  88. package/dist/list-box/README_CN.md +682 -0
  89. package/dist/lookup-editor/LookupEditor.svelte +15 -3
  90. package/dist/lookup-editor/LookupEditor.svelte.d.ts +3 -4
  91. package/dist/lookup-editor/README.md +684 -0
  92. package/dist/lookup-editor/README_CN.md +684 -0
  93. package/dist/memo-editor/MemoEditor.svelte +77 -27
  94. package/dist/memo-editor/MemoEditor.svelte.d.ts +6 -3
  95. package/dist/memo-editor/README.md +819 -0
  96. package/dist/memo-editor/README_CN.md +819 -0
  97. package/dist/message-box/README.md +398 -0
  98. package/dist/message-box/README_CN.md +398 -0
  99. package/dist/number-editor/NumberEditor.svelte +2 -2
  100. package/dist/number-editor/NumberEditor.svelte.d.ts +1 -1
  101. package/dist/number-editor/README.md +353 -22
  102. package/dist/number-editor/README_CN.md +357 -0
  103. package/dist/number-range/README.md +443 -0
  104. package/dist/number-range/README_CN.md +443 -0
  105. package/dist/options-multi-select/OptionsMultiSelect.svelte +87 -12
  106. package/dist/options-multi-select/OptionsMultiSelect.svelte.d.ts +3 -1
  107. package/dist/options-multi-select/README.md +480 -0
  108. package/dist/options-multi-select/README_CN.md +480 -0
  109. package/dist/options-select/OptionsSelect.svelte +36 -5
  110. package/dist/options-select/OptionsSelect.svelte.d.ts +3 -4
  111. package/dist/options-select/README.md +632 -0
  112. package/dist/options-select/README_CN.md +632 -0
  113. package/dist/page/README.md +605 -0
  114. package/dist/page/README_CN.md +605 -0
  115. package/dist/pagination/README.md +946 -0
  116. package/dist/pagination/README_CN.md +946 -0
  117. package/dist/pagination-panel/README.md +1075 -0
  118. package/dist/pagination-panel/README_CN.md +1075 -0
  119. package/dist/popup-hint/README.md +841 -0
  120. package/dist/popup-hint/README_CN.md +840 -0
  121. package/dist/progress-bar/README.md +242 -0
  122. package/dist/progress-bar/README_CN.md +242 -0
  123. package/dist/progress-step-bar/README.md +316 -0
  124. package/dist/progress-step-bar/README_CN.md +316 -0
  125. package/dist/prompts-text-editor/PromptsTextEditor.svelte +6 -3
  126. package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +3 -1
  127. package/dist/prompts-text-editor/README.md +329 -0
  128. package/dist/prompts-text-editor/README_CN.md +329 -0
  129. package/dist/property-editor/README.md +969 -0
  130. package/dist/property-editor/README_CN.md +969 -0
  131. package/dist/radio-button/README.md +372 -0
  132. package/dist/radio-button/README_CN.md +372 -0
  133. package/dist/radio-button/RadioButton.svelte +32 -3
  134. package/dist/radio-button/RadioButton.svelte.d.ts +12 -1
  135. package/dist/search-box/README.md +425 -0
  136. package/dist/search-box/README_CN.md +424 -0
  137. package/dist/search-box/SearchBox.svelte +22 -6
  138. package/dist/search-box/SearchBox.svelte.d.ts +4 -1
  139. package/dist/tabs/README.md +919 -0
  140. package/dist/tabs/README_CN.md +920 -0
  141. package/dist/tag/README.md +922 -0
  142. package/dist/tag/README_CN.md +922 -0
  143. package/dist/text-editor/PasswordEditor.svelte +17 -2
  144. package/dist/text-editor/PasswordEditor.svelte.d.ts +3 -3
  145. package/dist/text-editor/PasswordEditor_README.md +551 -0
  146. package/dist/text-editor/PasswordEditor_README_CN.md +551 -0
  147. package/dist/text-editor/README.md +466 -0
  148. package/dist/text-editor/README_CN.md +466 -0
  149. package/dist/text-editor/TextEditor.svelte +51 -19
  150. package/dist/text-editor/TextEditor.svelte.d.ts +0 -1
  151. package/dist/time-editor/README.md +498 -24
  152. package/dist/time-editor/README_CN.md +498 -0
  153. package/dist/time-editor/TimeEditor.svelte +7 -3
  154. package/dist/time-editor/TimeEditor.svelte.d.ts +3 -1
  155. package/dist/toast/README.md +667 -0
  156. package/dist/toast/README_CN.md +667 -0
  157. package/dist/transfer/README.md +795 -0
  158. package/dist/transfer/Transfer.svelte +6 -4
  159. package/dist/transfer/Transfer.svelte.d.ts +3 -1
  160. package/dist/tree-view/README.md +761 -0
  161. package/dist/tree-view/README_CN.md +761 -0
  162. package/dist/tree-view/TreeView.svelte +5 -3
  163. package/dist/tree-view/TreeView.svelte.d.ts +3 -1
  164. package/dist/unit-number-editor/README.md +546 -20
  165. package/dist/unit-number-editor/README_CN.md +525 -0
  166. package/dist/unit-number-editor/UnitNumberEditor.svelte +62 -8
  167. package/dist/unit-number-editor/UnitNumberEditor.svelte.d.ts +5 -1
  168. package/docs/form-field/cn/README_CN.md +364 -0
  169. package/docs/form-field/en/README.md +364 -0
  170. package/docs/form-panel/flex-form/cn/README_CN.md +586 -0
  171. package/docs/form-panel/flex-form/en/README.md +586 -0
  172. package/docs/form-panel/flex-row-form/cn/README_CN.md +787 -0
  173. package/docs/form-panel/flex-row-form/en/README.md +787 -0
  174. package/docs/form-panel/grid-form/en/README.md +744 -0
  175. package/package.json +1 -1
  176. package/dist/drawer/README-CN.md +0 -1
@@ -14,13 +14,15 @@
14
14
  export let activeNode: any = null;
15
15
  export {className as class};
16
16
  export let isVisible: NodeVisibleFun = null as unknown as NodeVisibleFun;
17
- export let onSelectionChange: OnNodeSelectionChange = null as unknown as OnNodeSelectionChange;
17
+ export let onchange: OnNodeSelectionChange = null as unknown as OnNodeSelectionChange;
18
+ export let onfocus: ((event: FocusEvent) => void) | null = null;
19
+ export let onblur: ((event: FocusEvent) => void) | null = null;
18
20
  export let onContextMenu: OnContextMenu = null as unknown as OnContextMenu;
19
21
  export let checkIsDirectory: CheckIsDirectory<any>;
20
22
  let className: string = "";
21
23
 
22
24
  const onNodeSelectionChange = async (node: TreeNode<any>): Promise<boolean> => {
23
- let accept: boolean = (await onSelectionChange?.(node));
25
+ let accept: boolean = (await onchange?.(node));
24
26
  accept = accept == null ? true : accept;
25
27
  if (accept == null || accept == true) {
26
28
  activeNode = node;
@@ -29,7 +31,7 @@
29
31
  }
30
32
 
31
33
  </script>
32
- <div class="uniface-tree-view {className}" {style}>
34
+ <div class="uniface-tree-view {className}" {style} on:focus={onfocus} on:blur={onblur} tabindex="0">
33
35
  <div>
34
36
  {#each nodes as node}
35
37
  <TreeNodeView {activeNode} {node} {textField} {lazyLoader} {onNodeSelectionChange} {isVisible} {checkIsDirectory} {onContextMenu}/>
@@ -22,7 +22,9 @@ declare const TreeView: $$__sveltets_2_IsomorphicComponent<{
22
22
  activeNode?: any;
23
23
  class?: string;
24
24
  isVisible?: NodeVisibleFun;
25
- onSelectionChange?: OnNodeSelectionChange;
25
+ onchange?: OnNodeSelectionChange;
26
+ onfocus?: ((event: FocusEvent) => void) | null;
27
+ onblur?: ((event: FocusEvent) => void) | null;
26
28
  onContextMenu?: OnContextMenu;
27
29
  checkIsDirectory: CheckIsDirectory<any>;
28
30
  }, {
@@ -1,26 +1,552 @@
1
- # NumberEditor
1
+ # UnitNumberEditor
2
2
 
3
- ## 使用方法
3
+ A specialized numeric input component with unit conversion functionality. Allows users to input numbers with different units (like kg, lb, cm, inch) and automatically converts between them. Features a dropdown unit selector and automatic ratio-based conversions.
4
4
 
5
- ```sveltehtml
6
- <NumberEditor filled max={500} suffix="KG" compact/>
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @ticatec/uniface-element
9
+ ```
10
+
11
+ ## Import
12
+
13
+ ```typescript
14
+ import UnitNumberEditor, { type UnitOption } from "@ticatec/uniface-element/UnitNumberEditor";
15
+ ```
16
+
17
+ ## Basic Usage
18
+
19
+ ```svelte
20
+ <script>
21
+ import UnitNumberEditor, { type UnitOption } from "@ticatec/uniface-element/UnitNumberEditor";
22
+
23
+ let weightValue = 75; // Standard unit value (kg)
24
+ let weightUnit = 'kg';
25
+
26
+ const weightUnits: UnitOption[] = [
27
+ { code: 'kg', text: 'Kilograms', ratio: 1, precision: 2 },
28
+ { code: 'lb', text: 'Pounds', ratio: 2.205, precision: 2 },
29
+ { code: 'g', text: 'Grams', ratio: 1000, precision: 0 }
30
+ ];
31
+ </script>
32
+
33
+ <UnitNumberEditor
34
+ bind:value={weightValue}
35
+ bind:unitCode={weightUnit}
36
+ units={weightUnits}
37
+ placeholder="Enter weight"
38
+ />
39
+ ```
40
+
41
+ ## Props
42
+
43
+ | Prop | Type | Default | Description |
44
+ |------|------|---------|-------------|
45
+ | `value` | `number \| null` | Required | Numeric value in standard unit |
46
+ | `unitCode` | `string` | Required | Current selected unit code |
47
+ | `units` | `Array<UnitOption>` | Required | Available unit options |
48
+ | `disabled` | `boolean` | `false` | Whether the input is disabled |
49
+ | `readonly` | `boolean` | `false` | Whether the input is read-only |
50
+ | `variant` | `"" \| "plain" \| "outlined" \| "filled"` | `""` | Input visual variant |
51
+ | `compact` | `boolean` | `false` | Whether to use compact spacing |
52
+ | `style` | `string` | `""` | Additional CSS styles |
53
+ | `prefix` | `string` | `""` | Text prefix to display |
54
+ | `allowNegative` | `boolean` | `false` | Whether to allow negative numbers |
55
+ | `displayMode` | `DisplayMode` | `DisplayMode.Edit` | Display mode (Edit/View) |
56
+ | `removable` | `boolean` | `true` | Whether to show clear button |
57
+ | `menu$height` | `number` | `0` | Fixed height for unit dropdown |
58
+ | `placeholder` | `string` | `""` | Placeholder text |
59
+ | `class` | `string` | `""` | CSS class name |
60
+ | `onchange` | `OnChangeHandler<number \| null>` | `null` | Callback when value changes |
61
+ | `onfocus` | `((event: FocusEvent) => void) \| null` | `null` | Callback when input gains focus |
62
+ | `onblur` | `((event: FocusEvent) => void) \| null` | `null` | Callback when input loses focus |
63
+
64
+ ## UnitOption Interface
65
+
66
+ ```typescript
67
+ interface UnitOption {
68
+ code: string; // Unit identifier (e.g., 'kg', 'lb')
69
+ text?: string; // Display name (e.g., 'Kilograms')
70
+ ratio?: number; // Conversion ratio to standard unit
71
+ precision?: number; // Decimal places for this unit
72
+ max?: number; // Maximum value for this unit
73
+ min?: number; // Minimum value for this unit
74
+ }
75
+ ```
76
+
77
+ ## Methods
78
+
79
+ | Method | Description |
80
+ |--------|-------------|
81
+ | `setFocus()` | Programmatically focus the input |
82
+
83
+ ## Examples
84
+
85
+ ### Weight Converter
86
+
87
+ ```svelte
88
+ <script>
89
+ import UnitNumberEditor, { type UnitOption } from "@ticatec/uniface-element/UnitNumberEditor";
90
+
91
+ let weight = 70; // 70 kg as standard unit
92
+ let weightUnit = 'kg';
93
+
94
+ const weightUnits: UnitOption[] = [
95
+ { code: 'kg', text: 'Kilograms', ratio: 1, precision: 2 },
96
+ { code: 'lb', text: 'Pounds', ratio: 2.20462, precision: 2 },
97
+ { code: 'g', text: 'Grams', ratio: 1000, precision: 0 },
98
+ { code: 'oz', text: 'Ounces', ratio: 35.274, precision: 2 }
99
+ ];
100
+
101
+ function handleWeightChange(newWeight) {
102
+ console.log(`Weight changed: ${newWeight} kg`);
103
+ }
104
+ </script>
105
+
106
+ <div class="converter">
107
+ <label>Weight:</label>
108
+ <UnitNumberEditor
109
+ bind:value={weight}
110
+ bind:unitCode={weightUnit}
111
+ units={weightUnits}
112
+ onchange={handleWeightChange}
113
+ placeholder="Enter weight"
114
+ />
115
+ </div>
116
+
117
+ <style>
118
+ .converter {
119
+ margin-bottom: 16px;
120
+ }
121
+
122
+ label {
123
+ display: block;
124
+ margin-bottom: 4px;
125
+ font-weight: 500;
126
+ }
127
+ </style>
128
+ ```
129
+
130
+ ### Distance Measurement
131
+
132
+ ```svelte
133
+ <script>
134
+ import UnitNumberEditor, { type UnitOption } from "@ticatec/uniface-element/UnitNumberEditor";
135
+
136
+ let distance = null;
137
+ let distanceUnit = 'm';
138
+
139
+ const distanceUnits: UnitOption[] = [
140
+ { code: 'm', text: 'Meters', ratio: 1, precision: 2 },
141
+ { code: 'ft', text: 'Feet', ratio: 3.28084, precision: 2 },
142
+ { code: 'in', text: 'Inches', ratio: 39.3701, precision: 1 },
143
+ { code: 'cm', text: 'Centimeters', ratio: 100, precision: 0 },
144
+ { code: 'mm', text: 'Millimeters', ratio: 1000, precision: 0 }
145
+ ];
146
+ </script>
147
+
148
+ <div class="form-group">
149
+ <label>Distance:</label>
150
+ <UnitNumberEditor
151
+ bind:value={distance}
152
+ bind:unitCode={distanceUnit}
153
+ units={distanceUnits}
154
+ placeholder="Enter distance"
155
+ />
156
+ </div>
157
+
158
+ {#if distance !== null}
159
+ <div class="conversion-display">
160
+ <h4>Conversions:</h4>
161
+ {#each distanceUnits as unit}
162
+ <p>
163
+ {unit.text}: {distance !== null ? (distance * (unit.ratio ?? 1)).toFixed(unit.precision ?? 2) : 'N/A'} {unit.code}
164
+ </p>
165
+ {/each}
166
+ </div>
167
+ {/if}
168
+
169
+ <style>
170
+ .form-group {
171
+ margin-bottom: 16px;
172
+ }
173
+
174
+ .conversion-display {
175
+ background: #f8f9fa;
176
+ padding: 16px;
177
+ border-radius: 4px;
178
+ margin-top: 16px;
179
+ }
180
+
181
+ .conversion-display h4 {
182
+ margin: 0 0 8px 0;
183
+ }
184
+
185
+ .conversion-display p {
186
+ margin: 4px 0;
187
+ font-family: monospace;
188
+ }
189
+ </style>
7
190
  ```
8
191
 
9
- ## 属性
10
- | 属性 | 描述 | 类型 |
11
- |---|------------------|-----------------|
12
- | disabled | 当前的数字输入框是否可用 | true / false |
13
- | readonly | 当前的数字输入框为只读或者可编辑 | true / false |
14
- | outlined | 当前的是否带边框 | true / false |
15
- | filled | 当前输入框是否填充 | true / false |
16
- | compact | 按照紧凑格式显示 | true / false |
17
- | style | 自定义style | 字符串 |
18
- | value | 值 | true / false |
19
- | precision | 精度 | 整数 |
20
- | suffix | 后缀 | 字符 |
21
- | prefix | 前缀 | 字符 |
22
- | allowNegative | 是否可以是负数 | true / false |
23
- | displayMode | 最小值 | 0(格式显示) / 1(正常) |
24
- | max | 最大值 | 数字 |
192
+ ### Temperature Converter
193
+
194
+ ```svelte
195
+ <script>
196
+ import UnitNumberEditor, { type UnitOption } from "@ticatec/uniface-element/UnitNumberEditor";
197
+
198
+ let temperature = 20; // 20°C as standard
199
+ let tempUnit = 'C';
200
+
201
+ // Note: Temperature conversions need special handling due to offset-based conversion
202
+ // This example shows a simplified approach - real implementation would need custom conversion logic
203
+ const temperatureUnits: UnitOption[] = [
204
+ { code: 'C', text: '°Celsius', ratio: 1, precision: 1 },
205
+ { code: 'F', text: '°Fahrenheit', ratio: 1.8, precision: 1 }, // Simplified - doesn't account for +32 offset
206
+ { code: 'K', text: 'Kelvin', ratio: 1, precision: 2 } // Simplified - doesn't account for +273.15 offset
207
+ ];
208
+
209
+ // For accurate temperature conversion, you'd implement custom conversion logic
210
+ function convertTemperature(value, fromUnit, toUnit) {
211
+ if (value === null) return null;
212
+
213
+ // Convert to Celsius first
214
+ let celsius = value;
215
+ if (fromUnit === 'F') celsius = (value - 32) / 1.8;
216
+ if (fromUnit === 'K') celsius = value - 273.15;
217
+
218
+ // Convert from Celsius to target unit
219
+ if (toUnit === 'F') return celsius * 1.8 + 32;
220
+ if (toUnit === 'K') return celsius + 273.15;
221
+ return celsius;
222
+ }
223
+ </script>
224
+
225
+ <div class="form-group">
226
+ <label>Temperature:</label>
227
+ <UnitNumberEditor
228
+ bind:value={temperature}
229
+ bind:unitCode={tempUnit}
230
+ units={temperatureUnits}
231
+ placeholder="Enter temperature"
232
+ allowNegative={true}
233
+ />
234
+ </div>
235
+ ```
236
+
237
+ ### With Event Handlers
238
+
239
+ ```svelte
240
+ <script>
241
+ import UnitNumberEditor, { type UnitOption } from "@ticatec/uniface-element/UnitNumberEditor";
242
+
243
+ let value = null;
244
+ let unit = 'kg';
245
+ let isFocused = false;
246
+
247
+ const units: UnitOption[] = [
248
+ { code: 'kg', text: 'Kilograms', ratio: 1, precision: 2 },
249
+ { code: 'lb', text: 'Pounds', ratio: 2.20462, precision: 2 }
250
+ ];
251
+
252
+ function handleChange(newValue) {
253
+ console.log('Value changed:', newValue);
254
+ }
255
+
256
+ function handleFocus(event) {
257
+ console.log('Input focused');
258
+ isFocused = true;
259
+ }
260
+
261
+ function handleBlur(event) {
262
+ console.log('Input blurred');
263
+ isFocused = false;
264
+ }
265
+ </script>
266
+
267
+ <UnitNumberEditor
268
+ bind:value
269
+ bind:unitCode={unit}
270
+ {units}
271
+ onchange={handleChange}
272
+ onfocus={handleFocus}
273
+ onblur={handleBlur}
274
+ placeholder="Enter value"
275
+ />
276
+
277
+ {#if isFocused}
278
+ <p>Input is currently focused</p>
279
+ {/if}
280
+ ```
281
+
282
+ ### Different Variants
283
+
284
+ ```svelte
285
+ <script>
286
+ import UnitNumberEditor, { type UnitOption } from "@ticatec/uniface-element/UnitNumberEditor";
287
+
288
+ let value1 = 100, value2 = 200, value3 = 300;
289
+ let unit1 = 'm', unit2 = 'm', unit3 = 'm';
290
+
291
+ const units: UnitOption[] = [
292
+ { code: 'm', text: 'Meters', ratio: 1, precision: 2 },
293
+ { code: 'ft', text: 'Feet', ratio: 3.28084, precision: 2 }
294
+ ];
295
+ </script>
296
+
297
+ <!-- Default variant -->
298
+ <UnitNumberEditor bind:value={value1} bind:unitCode={unit1} {units} placeholder="Default" />
299
+
300
+ <!-- Outlined variant -->
301
+ <UnitNumberEditor bind:value={value2} bind:unitCode={unit2} {units} variant="outlined" placeholder="Outlined" />
302
+
303
+ <!-- Filled variant -->
304
+ <UnitNumberEditor bind:value={value3} bind:unitCode={unit3} {units} variant="filled" placeholder="Filled" />
305
+ ```
306
+
307
+ ### With Min/Max Constraints
308
+
309
+ ```svelte
310
+ <script>
311
+ import UnitNumberEditor, { type UnitOption } from "@ticatec/uniface-element/UnitNumberEditor";
312
+
313
+ let age = null;
314
+ let ageUnit = 'years';
315
+
316
+ const ageUnits: UnitOption[] = [
317
+ { code: 'years', text: 'Years', ratio: 1, precision: 0, min: 0, max: 150 },
318
+ { code: 'months', text: 'Months', ratio: 12, precision: 0, min: 0, max: 1800 },
319
+ { code: 'days', text: 'Days', ratio: 365.25, precision: 0, min: 0, max: 54750 }
320
+ ];
321
+ </script>
322
+
323
+ <div class="form-group">
324
+ <label>Age:</label>
325
+ <UnitNumberEditor
326
+ bind:value={age}
327
+ bind:unitCode={ageUnit}
328
+ units={ageUnits}
329
+ placeholder="Enter age"
330
+ />
331
+ </div>
332
+
333
+ {#if age !== null}
334
+ <p>Age: {age} {ageUnits.find(u => u.code === ageUnit)?.text?.toLowerCase()}</p>
335
+ {/if}
336
+ ```
337
+
338
+ ### Disabled and Readonly States
339
+
340
+ ```svelte
341
+ <script>
342
+ import UnitNumberEditor, { type UnitOption } from "@ticatec/uniface-element/UnitNumberEditor";
343
+
344
+ let normalValue = 50;
345
+ let readonlyValue = 75;
346
+ let disabledValue = null;
347
+ let unit = 'kg';
348
+
349
+ const units: UnitOption[] = [
350
+ { code: 'kg', text: 'Kilograms', ratio: 1, precision: 2 },
351
+ { code: 'lb', text: 'Pounds', ratio: 2.20462, precision: 2 }
352
+ ];
353
+ </script>
354
+
355
+ <!-- Normal input -->
356
+ <UnitNumberEditor bind:value={normalValue} bind:unitCode={unit} {units} placeholder="Normal" />
357
+
358
+ <!-- Readonly input -->
359
+ <UnitNumberEditor bind:value={readonlyValue} bind:unitCode={unit} {units} readonly />
360
+
361
+ <!-- Disabled input -->
362
+ <UnitNumberEditor bind:value={disabledValue} bind:unitCode={unit} {units} disabled placeholder="Disabled" />
363
+ ```
364
+
365
+ ### Recipe Ingredient Converter
366
+
367
+ ```svelte
368
+ <script>
369
+ import UnitNumberEditor, { type UnitOption } from "@ticatec/uniface-element/UnitNumberEditor";
370
+ import Button from "@ticatec/uniface-element/Button";
371
+
372
+ let ingredients = [
373
+ { name: 'Flour', amount: 500, unit: 'g' },
374
+ { name: 'Sugar', amount: 200, unit: 'g' },
375
+ { name: 'Milk', amount: 250, unit: 'ml' }
376
+ ];
377
+
378
+ const weightUnits: UnitOption[] = [
379
+ { code: 'g', text: 'Grams', ratio: 1, precision: 0 },
380
+ { code: 'kg', text: 'Kilograms', ratio: 0.001, precision: 3 },
381
+ { code: 'oz', text: 'Ounces', ratio: 0.035274, precision: 2 },
382
+ { code: 'lb', text: 'Pounds', ratio: 0.00220462, precision: 4 }
383
+ ];
384
+
385
+ const volumeUnits: UnitOption[] = [
386
+ { code: 'ml', text: 'Milliliters', ratio: 1, precision: 0 },
387
+ { code: 'l', text: 'Liters', ratio: 0.001, precision: 3 },
388
+ { code: 'cup', text: 'Cups', ratio: 0.00422675, precision: 3 },
389
+ { code: 'tbsp', text: 'Tablespoons', ratio: 0.067628, precision: 2 }
390
+ ];
391
+
392
+ function getUnitsForIngredient(name) {
393
+ return name.toLowerCase().includes('milk') ? volumeUnits : weightUnits;
394
+ }
395
+
396
+ function addIngredient() {
397
+ ingredients = [...ingredients, { name: '', amount: null, unit: 'g' }];
398
+ }
399
+
400
+ function removeIngredient(index) {
401
+ ingredients = ingredients.filter((_, i) => i !== index);
402
+ }
403
+ </script>
404
+
405
+ <div class="recipe-converter">
406
+ <h3>Recipe Ingredient Converter</h3>
407
+
408
+ {#each ingredients as ingredient, index}
409
+ <div class="ingredient-row">
410
+ <input
411
+ bind:value={ingredient.name}
412
+ placeholder="Ingredient name"
413
+ class="ingredient-name"
414
+ />
415
+ <UnitNumberEditor
416
+ bind:value={ingredient.amount}
417
+ bind:unitCode={ingredient.unit}
418
+ units={getUnitsForIngredient(ingredient.name)}
419
+ placeholder="Amount"
420
+ compact
421
+ />
422
+ <Button
423
+ label="×"
424
+ onClick={() => removeIngredient(index)}
425
+ style="width: 32px; height: 32px;"
426
+ />
427
+ </div>
428
+ {/each}
429
+
430
+ <Button label="Add Ingredient" onClick={addIngredient} />
431
+ </div>
432
+
433
+ <style>
434
+ .recipe-converter {
435
+ max-width: 600px;
436
+ padding: 20px;
437
+ border: 1px solid #ddd;
438
+ border-radius: 8px;
439
+ }
440
+
441
+ .ingredient-row {
442
+ display: grid;
443
+ grid-template-columns: 1fr 1fr auto;
444
+ gap: 12px;
445
+ align-items: center;
446
+ margin-bottom: 12px;
447
+ }
448
+
449
+ .ingredient-name {
450
+ padding: 8px 12px;
451
+ border: 1px solid #ccc;
452
+ border-radius: 4px;
453
+ font-size: 14px;
454
+ }
455
+
456
+ h3 {
457
+ margin-bottom: 20px;
458
+ }
459
+ </style>
460
+ ```
461
+
462
+ ### Programmatic Focus
463
+
464
+ ```svelte
465
+ <script>
466
+ import UnitNumberEditor, { type UnitOption } from "@ticatec/uniface-element/UnitNumberEditor";
467
+ import Button from "@ticatec/uniface-element/Button";
468
+
469
+ let unitEditor;
470
+ let value = null;
471
+ let unit = 'kg';
472
+
473
+ const units: UnitOption[] = [
474
+ { code: 'kg', text: 'Kilograms', ratio: 1, precision: 2 },
475
+ { code: 'lb', text: 'Pounds', ratio: 2.20462, precision: 2 }
476
+ ];
477
+
478
+ function focusInput() {
479
+ unitEditor.setFocus();
480
+ }
481
+ </script>
482
+
483
+ <Button label="Focus Input" onClick={focusInput} />
484
+
485
+ <UnitNumberEditor
486
+ bind:this={unitEditor}
487
+ bind:value
488
+ bind:unitCode={unit}
489
+ {units}
490
+ placeholder="Click button to focus me"
491
+ />
492
+ ```
493
+
494
+ ## Features
495
+
496
+ - **Automatic Conversion**: Seamless conversion between different units based on ratio
497
+ - **Flexible Precision**: Each unit can have its own decimal precision
498
+ - **Validation**: Min/max constraints per unit with automatic validation
499
+ - **Clear Functionality**: Built-in clear button to reset values
500
+ - **Focus Management**: Proper focus handling for accessibility
501
+ - **Custom Styling**: Multiple visual variants and custom CSS support
502
+ - **Unit Dropdown**: Interactive dropdown for unit selection
503
+ - **Negative Numbers**: Optional support for negative values
504
+ - **Prefix Support**: Add text prefixes for enhanced context
505
+
506
+ ## Unit Conversion Logic
507
+
508
+ The component uses a ratio-based conversion system:
509
+
510
+ 1. **Standard Unit**: One unit should have `ratio: 1` as the base unit
511
+ 2. **Conversion**: Other units multiply by their ratio to convert to the standard unit
512
+ 3. **Display**: Values are automatically converted for display in the selected unit
513
+ 4. **Storage**: The `value` prop always contains the value in the standard unit
514
+
515
+ Example:
516
+ ```typescript
517
+ // If kg is standard (ratio: 1) and lb has ratio: 2.20462
518
+ // User enters 100 lb → stored as ~45.36 kg
519
+ // User switches to kg → displays ~45.36 kg
520
+ ```
521
+
522
+ ## Accessibility
523
+
524
+ - Proper keyboard navigation between input and dropdown
525
+ - Screen reader compatible with semantic HTML
526
+ - Focus indicators for interactive elements
527
+ - ARIA attributes for dropdown accessibility
528
+ - Clear visual feedback for interaction states
529
+
530
+ ## Best Practices
531
+
532
+ 1. **Standard Unit**: Always define one unit with `ratio: 1` as your base unit
533
+ 2. **Precision**: Set appropriate precision for each unit (whole numbers vs decimals)
534
+ 3. **Constraints**: Use min/max values to prevent invalid inputs
535
+ 4. **Unit Names**: Provide clear, descriptive unit names in the `text` property
536
+ 5. **Conversion Logic**: For complex conversions (like temperature), implement custom logic
537
+ 6. **Validation**: Add additional validation in change handlers if needed
538
+
539
+ ## Browser Support
540
+
541
+ - Modern browsers with full input event support
542
+ - Compatible with Svelte 5+
543
+ - Keyboard navigation support
544
+ - Touch-friendly dropdown interface
545
+ - Full TypeScript support
25
546
 
547
+ ## Related Components
26
548
 
549
+ - `NumberEditor` - Basic numeric input without units
550
+ - `TextEditor` - Text input component
551
+ - `OptionsSelect` - Dropdown selection component
552
+ - `TimeEditor` - Time input with time units