@ticatec/uniface-element 5.0.1 → 5.0.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.
Files changed (255) hide show
  1. package/README.md +29 -54
  2. package/README_CN.md +37 -57
  3. package/dist/base-calendar/CalendarBase.svelte +29 -6
  4. package/dist/base-calendar/CalendarBase.svelte.d.ts +4 -0
  5. package/dist/base-calendar/MonthPickupPanel.svelte +19 -6
  6. package/dist/base-calendar/MonthPickupPanel.svelte.d.ts +1 -1
  7. package/dist/base-calendar/MonthlyCalendar.svelte +18 -2
  8. package/dist/base-calendar/YearPickupPanel.svelte +24 -6
  9. package/dist/base-calendar/YearPickupPanel.svelte.d.ts +1 -1
  10. package/dist/composite/pagination_panel/PaginationPanel.svelte +2 -0
  11. package/dist/data_display/card/CommonCardActionBar.svelte +34 -14
  12. package/dist/data_display/concise_data_table/Column.d.ts +6 -0
  13. package/dist/data_display/concise_data_table/ConciseListTable.svelte +4 -3
  14. package/dist/data_display/concise_data_table/DataCell.svelte +3 -3
  15. package/dist/data_display/list_box/ListBox.svelte +90 -15
  16. package/dist/data_display/list_box/ListBox.svelte.d.ts +4 -0
  17. package/dist/data_display/tree_view/TreeNodeView.svelte +25 -4
  18. package/dist/data_table/DataTable.svelte +5 -5
  19. package/dist/data_table/DataTable.svelte.d.ts +36 -16
  20. package/dist/data_table/lib/ActionsColumn.d.ts +2 -2
  21. package/dist/data_table/lib/DataColumn.d.ts +7 -1
  22. package/dist/data_table/lib/RowAction.d.ts +5 -5
  23. package/dist/data_table/parts/FixedHeaderPanel.svelte +18 -3
  24. package/dist/data_table/parts/FixedRow.svelte +10 -1
  25. package/dist/data_table/parts/HrefCell.svelte +1 -1
  26. package/dist/data_table/parts/TableHeaderPanel.svelte +18 -2
  27. package/dist/data_table/parts/TextCell.svelte +2 -2
  28. package/dist/form/attachment_files/AttachmentEditor.svelte +9 -9
  29. package/dist/form/attachment_files/FileRender.svelte +1 -1
  30. package/dist/form/attachment_files/FileUploadPanel.svelte +5 -1
  31. package/dist/form/cascade_options_select/CascadeOptionSelect.svelte +10 -2
  32. package/dist/form/cascade_options_select/OptionsBox.svelte +48 -2
  33. package/dist/form/color_picker/ColorPickerPanel.svelte +23 -20
  34. package/dist/form/color_picker/ColorPickerPanel.svelte.d.ts +5 -18
  35. package/dist/form/common_editor/CommonEditor.svelte +18 -4
  36. package/dist/form/common_editor/CommonPicker.svelte +11 -4
  37. package/dist/form/common_editor/CommonPopupEditor.svelte +8 -1
  38. package/dist/form/common_range_editor/CommonRangeEditor.svelte +11 -2
  39. package/dist/form/date_picker/DatePicker.svelte +1 -1
  40. package/dist/form/date_picker/DateTimePicker.svelte +1 -1
  41. package/dist/form/date_picker/ScrollBar.svelte +20 -12
  42. package/dist/form/date_picker/ScrollBar.svelte.d.ts +4 -18
  43. package/dist/form/date_range/DateRangeEditor.svelte +11 -3
  44. package/dist/form/group_box/group-check-box/GroupCheckBox.svelte +6 -1
  45. package/dist/form/group_box/group-radio-box/GroupRadioBox.svelte +6 -1
  46. package/dist/form/image-files/ImageFilesField.svelte +51 -7
  47. package/dist/form/image-files/ImagePreview.svelte +8 -2
  48. package/dist/form/image-files/ImageRender.svelte +69 -11
  49. package/dist/form/input_options_select/InputOptionsSelect.svelte +10 -2
  50. package/dist/form/lookup_editor/LookupEditor.svelte +9 -2
  51. package/dist/form/options_multi_select/OptionsMultiSelect.svelte +19 -3
  52. package/dist/form/options_select/OptionsSelect.svelte +15 -6
  53. package/dist/form/options_select/OptionsSelect.svelte.d.ts +39 -17
  54. package/dist/form/prompts_text_editor/PromptsTextEditor.svelte +10 -2
  55. package/dist/form/switch/Switch.svelte +4 -4
  56. package/dist/form/unit-number-editor/UnitNumberEditor.svelte +10 -2
  57. package/dist/general/button/Button.svelte +3 -0
  58. package/dist/general/button/Button.svelte.d.ts +1 -0
  59. package/dist/general/button/IconButton.svelte +3 -1
  60. package/dist/general/button/IconButton.svelte.d.ts +1 -0
  61. package/dist/general/button/TextButton.svelte +3 -0
  62. package/dist/general/button/TextButton.svelte.d.ts +1 -0
  63. package/dist/general/icon/Icon.svelte +18 -1
  64. package/dist/general/tag/Tag.svelte +9 -1
  65. package/dist/navigation/nav_menu/NavigatorMenu.svelte +2 -2
  66. package/dist/navigation/nav_menu/NavigatorMenuItem.svelte +10 -1
  67. package/dist/navigation/navigator/Navigator.svelte +17 -17
  68. package/dist/navigation/page-stack/PageStack.svelte +160 -0
  69. package/dist/navigation/page-stack/PageStack.svelte.d.ts +24 -0
  70. package/dist/navigation/page-stack/PageStackContext.d.ts +25 -0
  71. package/dist/navigation/page-stack/PageStackContext.js +12 -0
  72. package/dist/navigation/page-stack/PageStackFrame.svelte +24 -0
  73. package/dist/navigation/page-stack/PageStackFrame.svelte.d.ts +11 -0
  74. package/dist/navigation/page-stack/README.md +154 -0
  75. package/dist/navigation/page-stack/README_CN.md +154 -0
  76. package/dist/navigation/page-stack/index.d.ts +6 -0
  77. package/dist/navigation/page-stack/index.js +4 -0
  78. package/dist/navigation/pagination/Pagination.svelte +114 -14
  79. package/dist/navigation/tabs/Tabs.svelte +42 -10
  80. package/dist/navigation/tabs/Tabs.svelte.d.ts +2 -2
  81. package/dist/overlay/common/FloatingPanel.svelte +3 -11
  82. package/dist/overlay/common/FullscreenOverlay.svelte +27 -3
  83. package/dist/overlay/common/FullscreenOverlay.svelte.d.ts +6 -27
  84. package/dist/overlay/common/ModalPopover.svelte +18 -2
  85. package/dist/overlay/common/Popover.svelte +56 -57
  86. package/dist/overlay/common/Popover.svelte.d.ts +1 -5
  87. package/dist/overlay/common/escapeClose.d.ts +28 -0
  88. package/dist/overlay/common/escapeClose.js +47 -0
  89. package/dist/overlay/common/focusTrap.d.ts +8 -0
  90. package/dist/overlay/common/focusTrap.js +83 -0
  91. package/dist/overlay/common/mountSingleton.d.ts +27 -0
  92. package/dist/overlay/common/mountSingleton.js +45 -0
  93. package/dist/overlay/common/outsideClick.d.ts +28 -0
  94. package/dist/overlay/common/outsideClick.js +20 -0
  95. package/dist/overlay/common/scrollLock.d.ts +8 -0
  96. package/dist/overlay/common/scrollLock.js +49 -0
  97. package/dist/overlay/context-menu/ContextMenu.svelte.js +2 -15
  98. package/dist/overlay/context-menu/ContextMenuPanel.svelte +13 -1
  99. package/dist/overlay/dialog/Dialog.svelte +46 -29
  100. package/dist/overlay/dialog/DialogManager.svelte.js +7 -9
  101. package/dist/overlay/drawer/Drawer.svelte +30 -3
  102. package/dist/overlay/indicator/Indicator.svelte.js +2 -15
  103. package/dist/overlay/indicator/IndicatorPanel.svelte +4 -1
  104. package/dist/overlay/message-box/MessageBox.svelte.js +2 -15
  105. package/dist/overlay/message-box/MessageBoxPanel.svelte +19 -3
  106. package/dist/overlay/toast/Toast.svelte.js +2 -15
  107. package/dist/overlay/toast/ToastPanel.svelte +1 -1
  108. package/dist/overlay/tooltip/Tooltip.svelte +1 -1
  109. package/dist/ticatec-uniface-web.css +102 -7
  110. package/dist/types.d.ts +4 -3
  111. package/docs/components/README.md +133 -0
  112. package/docs/components/accordion/README.md +60 -0
  113. package/docs/components/accordion/example.svelte +7 -0
  114. package/docs/components/action-bar/README.md +114 -0
  115. package/docs/components/action-bar/example.svelte +7 -0
  116. package/docs/components/app-top-bar/README.md +60 -0
  117. package/docs/components/app-top-bar/example.svelte +9 -0
  118. package/docs/components/attachment-files/README.md +332 -0
  119. package/docs/components/attachment-files/example.svelte +16 -0
  120. package/docs/components/box/README.md +63 -0
  121. package/docs/components/box/example.svelte +10 -0
  122. package/docs/components/breadcrumbs/README.md +86 -0
  123. package/docs/components/breadcrumbs/example.svelte +11 -0
  124. package/docs/components/button/README.md +103 -0
  125. package/docs/components/button/example.svelte +10 -0
  126. package/docs/components/card/README.md +113 -0
  127. package/docs/components/card/example.svelte +10 -0
  128. package/docs/components/cascade-options-select/README.md +162 -0
  129. package/docs/components/cascade-options-select/example.svelte +18 -0
  130. package/docs/components/checkbox/README.md +103 -0
  131. package/docs/components/checkbox/example.svelte +15 -0
  132. package/docs/components/classic-layout/README.md +76 -0
  133. package/docs/components/classic-layout/example.svelte +16 -0
  134. package/docs/components/color-picker/README.md +132 -0
  135. package/docs/components/color-picker/example.svelte +16 -0
  136. package/docs/components/columns-layout/README.md +70 -0
  137. package/docs/components/columns-layout/example.svelte +12 -0
  138. package/docs/components/common-dialog/README.md +109 -0
  139. package/docs/components/common-dialog/example.svelte +12 -0
  140. package/docs/components/concise-data-table/README.md +307 -0
  141. package/docs/components/concise-data-table/example.svelte +16 -0
  142. package/docs/components/context-menu/README.md +99 -0
  143. package/docs/components/context-menu/example.svelte +10 -0
  144. package/docs/components/criteria-field/README.md +69 -0
  145. package/docs/components/criteria-field/example.svelte +9 -0
  146. package/docs/components/data-table/README.md +365 -0
  147. package/docs/components/data-table/example.svelte +23 -0
  148. package/docs/components/date-picker/README.md +136 -0
  149. package/docs/components/date-picker/example.svelte +16 -0
  150. package/docs/components/date-range/README.md +122 -0
  151. package/docs/components/date-range/example.svelte +15 -0
  152. package/docs/components/date-time-picker/README.md +142 -0
  153. package/docs/components/date-time-picker/example.svelte +16 -0
  154. package/docs/components/dialog/README.md +174 -0
  155. package/docs/components/dialog/example.svelte +13 -0
  156. package/docs/components/dialog-board/README.md +41 -0
  157. package/docs/components/dialog-board/example.svelte +5 -0
  158. package/docs/components/drawer/README.md +70 -0
  159. package/docs/components/drawer/example.svelte +12 -0
  160. package/docs/components/flex-form/README.md +55 -0
  161. package/docs/components/flex-form/example.svelte +7 -0
  162. package/docs/components/flex-row-form/README.md +56 -0
  163. package/docs/components/flex-row-form/example.svelte +7 -0
  164. package/docs/components/form-field/README.md +84 -0
  165. package/docs/components/form-field/example.svelte +10 -0
  166. package/docs/components/full-screen-overlay/README.md +66 -0
  167. package/docs/components/full-screen-overlay/example.svelte +11 -0
  168. package/docs/components/grid-form/README.md +75 -0
  169. package/docs/components/grid-form/example.svelte +9 -0
  170. package/docs/components/group-check-box/README.md +147 -0
  171. package/docs/components/group-check-box/example.svelte +21 -0
  172. package/docs/components/group-radio-box/README.md +144 -0
  173. package/docs/components/group-radio-box/example.svelte +21 -0
  174. package/docs/components/header-layout/README.md +65 -0
  175. package/docs/components/header-layout/example.svelte +12 -0
  176. package/docs/components/icon/README.md +87 -0
  177. package/docs/components/icon/example.svelte +9 -0
  178. package/docs/components/icon-button/README.md +91 -0
  179. package/docs/components/icon-button/example.svelte +10 -0
  180. package/docs/components/image-files/README.md +174 -0
  181. package/docs/components/image-files/example.svelte +19 -0
  182. package/docs/components/indicator/README.md +53 -0
  183. package/docs/components/indicator/example.svelte +14 -0
  184. package/docs/components/input-options-select/README.md +163 -0
  185. package/docs/components/input-options-select/example.svelte +16 -0
  186. package/docs/components/list-box/ListItem.svelte +14 -0
  187. package/docs/components/list-box/README.md +221 -0
  188. package/docs/components/list-box/example.svelte +61 -0
  189. package/docs/components/lookup-editor/README.md +137 -0
  190. package/docs/components/lookup-editor/example.svelte +16 -0
  191. package/docs/components/memo-editor/README.md +143 -0
  192. package/docs/components/memo-editor/example.svelte +16 -0
  193. package/docs/components/message-box/README.md +68 -0
  194. package/docs/components/message-box/example.svelte +10 -0
  195. package/docs/components/navigator/README.md +75 -0
  196. package/docs/components/navigator/example.svelte +13 -0
  197. package/docs/components/navigator-menu/README.md +113 -0
  198. package/docs/components/navigator-menu/example.svelte +10 -0
  199. package/docs/components/number-editor/README.md +144 -0
  200. package/docs/components/number-editor/example.svelte +16 -0
  201. package/docs/components/number-range/README.md +116 -0
  202. package/docs/components/number-range/example.svelte +15 -0
  203. package/docs/components/options-multi-select/README.md +161 -0
  204. package/docs/components/options-multi-select/example.svelte +20 -0
  205. package/docs/components/options-select/README.md +160 -0
  206. package/docs/components/options-select/example.svelte +21 -0
  207. package/docs/components/page/README.md +77 -0
  208. package/docs/components/page/example.svelte +10 -0
  209. package/docs/components/pagination/README.md +88 -0
  210. package/docs/components/pagination/example.svelte +10 -0
  211. package/docs/components/pagination-panel/README.md +120 -0
  212. package/docs/components/pagination-panel/example.svelte +16 -0
  213. package/docs/components/popup-hint/README.md +44 -0
  214. package/docs/components/popup-hint/example.svelte +5 -0
  215. package/docs/components/progress-bar/README.md +64 -0
  216. package/docs/components/progress-bar/example.svelte +8 -0
  217. package/docs/components/progress-step-bar/README.md +93 -0
  218. package/docs/components/progress-step-bar/example.svelte +7 -0
  219. package/docs/components/prompts-text-editor/README.md +146 -0
  220. package/docs/components/prompts-text-editor/example.svelte +17 -0
  221. package/docs/components/radio-button/README.md +121 -0
  222. package/docs/components/radio-button/example.svelte +18 -0
  223. package/docs/components/rows-layout/README.md +70 -0
  224. package/docs/components/rows-layout/example.svelte +12 -0
  225. package/docs/components/search-box/README.md +136 -0
  226. package/docs/components/search-box/example.svelte +16 -0
  227. package/docs/components/separator/README.md +44 -0
  228. package/docs/components/separator/example.svelte +7 -0
  229. package/docs/components/sidebar-layout/README.md +65 -0
  230. package/docs/components/sidebar-layout/example.svelte +12 -0
  231. package/docs/components/split/README.md +48 -0
  232. package/docs/components/split/example.svelte +8 -0
  233. package/docs/components/switch/README.md +77 -0
  234. package/docs/components/switch/example.svelte +11 -0
  235. package/docs/components/tabs/README.md +127 -0
  236. package/docs/components/tabs/example.svelte +22 -0
  237. package/docs/components/tag/README.md +63 -0
  238. package/docs/components/tag/example.svelte +8 -0
  239. package/docs/components/text-button/README.md +90 -0
  240. package/docs/components/text-button/example.svelte +9 -0
  241. package/docs/components/text-editor/README.md +147 -0
  242. package/docs/components/text-editor/example.svelte +16 -0
  243. package/docs/components/time-editor/README.md +130 -0
  244. package/docs/components/time-editor/example.svelte +16 -0
  245. package/docs/components/toast/README.md +52 -0
  246. package/docs/components/toast/example.svelte +9 -0
  247. package/docs/components/tooltip/README.md +44 -0
  248. package/docs/components/tooltip/example.svelte +5 -0
  249. package/docs/components/transfer/README.md +109 -0
  250. package/docs/components/transfer/example.svelte +13 -0
  251. package/docs/components/tree-view/README.md +163 -0
  252. package/docs/components/tree-view/example.svelte +26 -0
  253. package/docs/components/unit-number-editor/README.md +192 -0
  254. package/docs/components/unit-number-editor/example.svelte +18 -0
  255. package/package.json +15 -7
@@ -6,6 +6,7 @@
6
6
  import FileUploadPanel from "../attachment_files/FileUploadPanel.svelte";
7
7
  import ImageRender from "./ImageRender.svelte";
8
8
  import ImagePreview from "./ImagePreview.svelte";
9
+ import FormEditor from "../FormEditor.svelte";
9
10
  import {getEditorVariant} from "../../unifaceContext";
10
11
  import type {EditorVariant} from "../types";
11
12
 
@@ -61,24 +62,67 @@
61
62
  $effect(() => {
62
63
  text = '<div>' + files.map(item => (item.name)).join("</div><div>") + '</div>';
63
64
  });
65
+
66
+ const handleUploadKeyDown = (e: KeyboardEvent) => {
67
+ if (e.key === 'Enter' || e.key === ' ') {
68
+ e.preventDefault();
69
+ showDialog();
70
+ }
71
+ };
64
72
  </script>
65
73
 
66
74
  <div class="uniface-images-field" {style}>
67
- <div class="uniface-common-editor {variant}" tabindex="-1">
75
+ <FormEditor {variant} {readonly} {disabled}>
68
76
  <div class="files-field">
69
77
  {#each files as file}
70
78
  <ImageRender {file} {readonly} onRemove={removeFile}
71
79
  onPreview={(file: ImageFile) => {showPreview = true; previewImgSrc = file.uri}}/>
72
80
  {/each}
81
+ {#if !disabled && !readonly}
82
+ <div class="editor-action-icon">
83
+ <i class="icon_google_file_upload" role="button" tabindex="0" aria-label="Upload image"
84
+ onclick={showDialog} onkeydown={handleUploadKeyDown}></i>
85
+ </div>
86
+ {/if}
73
87
  </div>
74
- {#if !disabled && !readonly}
75
- <div class="editor-action-icon">
76
- <i class="icon_google_file_upload" aria-hidden="true" onclick={showDialog}></i>
77
- </div>
78
- {/if}
79
- </div>
88
+ </FormEditor>
80
89
  {#if showUpload}
81
90
  <FileUploadPanel bind:visible={showUpload} accept="image/*" {maxFiles} onFileUploaded={appendNewFile} {uploadFile}/>
82
91
  {/if}
83
92
  <ImagePreview bind:visible={showPreview} src={previewImgSrc}/>
84
93
  </div>
94
+
95
+ <style>
96
+ .uniface-images-field {
97
+ width: 100%;
98
+ }
99
+
100
+ .files-field {
101
+ display: flex;
102
+ align-items: center;
103
+ width: 100%;
104
+ height: 52px;
105
+ min-width: 0;
106
+ overflow-x: auto;
107
+ overflow-y: hidden;
108
+ box-sizing: border-box;
109
+ }
110
+
111
+ .editor-action-icon {
112
+ flex: 0 0 auto;
113
+ cursor: pointer;
114
+ padding: 4px;
115
+ border-radius: 4px;
116
+ display: flex;
117
+ align-items: center;
118
+ color: inherit;
119
+ }
120
+
121
+ .editor-action-icon:hover {
122
+ background-color: rgba(0, 0, 0, 0.05);
123
+ }
124
+
125
+ .editor-action-icon i {
126
+ font-size: 22px;
127
+ }
128
+ </style>
@@ -60,7 +60,9 @@
60
60
  </script>
61
61
 
62
62
  {#if visible}
63
- <div class="uniface-image-preview-overlay" onclick={() => visible = false} aria-hidden="true">
63
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
64
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
65
+ <div class="uniface-image-preview-overlay" onclick={() => visible = false}>
64
66
  <div>
65
67
  <div style="width: 100%; height: 100%; overflow: auto">
66
68
  <div class="image-container"
@@ -74,7 +76,11 @@
74
76
  </button>
75
77
  </div>
76
78
  </div>
77
- <div class="toolbar" onclick={(e: Event) => e.stopPropagation()} aria-hidden="true">
79
+ <!-- onclick here only stops propagation to the backdrop's close handler;
80
+ the real controls are the IconButtons inside. -->
81
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
82
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
83
+ <div class="toolbar" onclick={(e: Event) => e.stopPropagation()}>
78
84
  <IconButton icon="icon_google_zoom_in" type="default" onclick={zoomIn}></IconButton>
79
85
  <IconButton icon="icon_google_zoom_out" type="default" onclick={zoomOut}></IconButton>
80
86
  <IconButton icon="icon_google_cancel" type="default" onclick={() => visible = false}></IconButton>
@@ -16,22 +16,80 @@
16
16
  const removeFile = () => {
17
17
  onRemove?.(file);
18
18
  }
19
+
20
+ const handleActionKeyDown = (handler: () => void) => (e: KeyboardEvent) => {
21
+ if (e.key === 'Enter' || e.key === ' ') {
22
+ e.preventDefault();
23
+ handler();
24
+ }
25
+ };
19
26
  </script>
20
27
 
21
- <div style="width: 80px; box-sizing: border-box; padding: 6px 8px;">
28
+ <div class="uniface-image-render">
22
29
  <div class="file-icon">
23
30
  <img src={file.thumbnail ?? file.uri} alt="" width="40px" height="40px"/>
24
31
  <div class="img-overlay">
25
- <div>
26
- <div class="action-icon" style="top: 15px;">
27
- <i class="icon_google_remove_red_eye" aria-hidden="true" onclick={() => onPreview?.(file)}></i>
28
- </div>
29
- {#if !readonly}
30
- <div class="action-icon" style="top: 35px;">
31
- <i class="icon_google_delete" aria-hidden="true" onclick={removeFile}></i>
32
- </div>
33
- {/if}
32
+ <div class="action-icon">
33
+ <i class="icon_google_remove_red_eye" role="button" tabindex="0" aria-label="Preview image"
34
+ onclick={() => onPreview?.(file)} onkeydown={handleActionKeyDown(() => onPreview?.(file))}></i>
34
35
  </div>
36
+ {#if !readonly}
37
+ <div class="action-icon">
38
+ <i class="icon_google_delete" role="button" tabindex="0" aria-label="Remove image"
39
+ onclick={removeFile} onkeydown={handleActionKeyDown(removeFile)}></i>
40
+ </div>
41
+ {/if}
35
42
  </div>
36
43
  </div>
37
- </div>
44
+ </div>
45
+
46
+ <style>
47
+ .uniface-image-render {
48
+ width: 80px;
49
+ box-sizing: border-box;
50
+ padding: 6px 8px;
51
+ }
52
+
53
+ .file-icon {
54
+ position: relative;
55
+ width: 40px;
56
+ height: 40px;
57
+ border-radius: 4px;
58
+ overflow: hidden;
59
+ background-color: rgba(0, 0, 0, 0.04);
60
+ }
61
+
62
+ .file-icon img {
63
+ display: block;
64
+ width: 100%;
65
+ height: 100%;
66
+ object-fit: cover;
67
+ }
68
+
69
+ .img-overlay {
70
+ position: absolute;
71
+ inset: 0;
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: center;
75
+ gap: 6px;
76
+ background-color: rgba(0, 0, 0, 0.45);
77
+ opacity: 0;
78
+ transition: opacity 0.15s ease;
79
+ }
80
+
81
+ .file-icon:hover .img-overlay,
82
+ .file-icon:focus-within .img-overlay {
83
+ opacity: 1;
84
+ }
85
+
86
+ .action-icon {
87
+ display: flex;
88
+ cursor: pointer;
89
+ color: #fff;
90
+ }
91
+
92
+ .action-icon i {
93
+ font-size: 16px;
94
+ }
95
+ </style>
@@ -163,6 +163,13 @@
163
163
  isOpen = false;
164
164
  };
165
165
 
166
+ const handleItemKeyDown = (data: any) => (e: KeyboardEvent) => {
167
+ if (e.key === 'Enter' || e.key === ' ') {
168
+ e.preventDefault();
169
+ handleItemClick(data)();
170
+ }
171
+ };
172
+
166
173
  const oninput = (event: Event) => {
167
174
  isUserTyping = true;
168
175
  if (!composing) {
@@ -211,9 +218,10 @@
211
218
  {/if}
212
219
  </div>
213
220
  {#snippet popupLayer()}
214
- <div class="options-popover" bind:this={scrollElement} style={mh} onscroll={handleScroll}>
221
+ <div class="options-popover" bind:this={scrollElement} style={mh} onscroll={handleScroll} role="listbox">
215
222
  {#each options as op (op[keyField])}
216
- <div class="option-item" onclick={handleItemClick(op)} aria-hidden="true">
223
+ <div class="option-item" onclick={handleItemClick(op)} onkeydown={handleItemKeyDown(op)}
224
+ role="option" tabindex="0" aria-selected={op[keyField] === value}>
217
225
  {#if ItemRender}
218
226
  <ItemRender item={op}/>
219
227
  {:else}
@@ -50,15 +50,22 @@
50
50
  }
51
51
  };
52
52
 
53
+ const handleActionKeyDown = (e: KeyboardEvent) => {
54
+ if (e.key === 'Enter' || e.key === ' ') {
55
+ e.preventDefault();
56
+ handleActionClick();
57
+ }
58
+ };
59
+
53
60
  </script>
54
61
 
55
62
  <CommonEditor {theme} {clear} {style} {tooltip} {error} {readonly} {disabled} {compact} {variant} textValue={text??''} canClean={!mandatory}>
56
63
  <input bind:this={editor} {placeholder} readonly value={text ?? ''} {onfocus} {onblur}/>
57
64
  {#snippet trailingIcon()}
58
65
  {#if !disabled && !readonly}
59
- <i class="icon_google_arrow_drop_down action_icon" role="list" aria-hidden="true"
66
+ <i class="icon_google_arrow_drop_down action_icon" role="button" tabindex="0" aria-label="Lookup"
60
67
  onmousedown={(event: MouseEvent)=> {event.preventDefault()}}
61
- onclick={handleActionClick}></i>
68
+ onclick={handleActionClick} onkeydown={handleActionKeyDown}></i>
62
69
  {/if}
63
70
  {/snippet}
64
71
  </CommonEditor>
@@ -138,6 +138,20 @@
138
138
  }
139
139
  }
140
140
 
141
+ const handleEditorKeyDown = (e: KeyboardEvent) => {
142
+ if (e.key === 'Enter' || e.key === ' ') {
143
+ e.preventDefault();
144
+ openPopupLayer();
145
+ }
146
+ };
147
+
148
+ const handleOptionKeyDown = (key: string, itemDisabled: boolean) => (e: KeyboardEvent) => {
149
+ if (!itemDisabled && (e.key === 'Enter' || e.key === ' ')) {
150
+ e.preventDefault();
151
+ toggleOption(key)(e as unknown as MouseEvent);
152
+ }
153
+ };
154
+
141
155
  const input$style = "position: absolute; left: 0; top: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none";
142
156
 
143
157
  </script>
@@ -145,7 +159,7 @@
145
159
  <CommonPicker {variant} {style} {compact} {tooltip} {error} {readonly} {disabled} {theme} {placeholder} {value} {mandatory} {clear}
146
160
  bind:isOpen {onblur} {onfocus} autoFit {input$style}>
147
161
  <div class="option-field">
148
- <div class="options-editor" onclick={openPopupLayer} aria-hidden="true" tabindex={-1} role="textbox">
162
+ <div class="options-editor" onclick={openPopupLayer} onkeydown={handleEditorKeyDown} tabindex="0" role="button" aria-haspopup="listbox" aria-expanded={isOpen}>
149
163
  {#if selectedList.length > 0 }
150
164
  {#each selectedList as code}
151
165
  <Tag style="flex-shrink: 0" size={compact ? 'small' : 'middle'} color={tagColor} variant={tagVariant}
@@ -164,12 +178,14 @@
164
178
  </div>
165
179
  </div>
166
180
  {#snippet popupLayer()}
167
- <div class="options-popover" style={mh}>
181
+ <div class="options-popover" style={mh} role="listbox" aria-multiselectable="true">
168
182
  {#each options as op}
169
183
  {#if hideOptions.indexOf(op[keyField]) < 0}
170
184
  {@const itemDisabled = disableOptions.indexOf(op[keyField]) > -1}
171
185
  <div class="option-item" class:disabled={itemDisabled} onclick={itemDisabled ? null : toggleOption(op[keyField])}
172
- aria-hidden="true">
186
+ onkeydown={handleOptionKeyDown(op[keyField], itemDisabled)}
187
+ role="option" tabindex={itemDisabled ? -1 : 0}
188
+ aria-selected={selectedList.indexOf(op[keyField])>-1} aria-disabled={itemDisabled}>
173
189
  <CheckBox style="width: 100%; pointer-events: none" {theme} value={selectedList.indexOf(op[keyField])>-1} disabled={itemDisabled}
174
190
  label={op[textField]}/>
175
191
  </div>
@@ -1,4 +1,4 @@
1
- <script lang="ts">
1
+ <script lang="ts" generics="Option extends Record<string, any> = any">
2
2
 
3
3
  import CommonPicker from "../common_editor/CommonPicker.svelte";
4
4
  import SearchBox from "../search_box/SearchBox.svelte";
@@ -8,7 +8,7 @@
8
8
  interface Props extends CommonPickerProps {
9
9
  emptyText?: string;
10
10
  value: any;
11
- options: Array<any>;
11
+ options: Array<Option>;
12
12
  keyField?: string;
13
13
  textField?: string;
14
14
  menu$height?: number;
@@ -16,7 +16,7 @@
16
16
  hideOptions?: Array<string>;
17
17
  itemRender?: any;
18
18
  filterPlaceholder?: string;
19
- filterFunction?: (option: any, keyword: string) => boolean;
19
+ filterFunction?: (option: Option, keyword: string) => boolean;
20
20
  noResultsText?: string;
21
21
  }
22
22
 
@@ -130,6 +130,13 @@
130
130
  }
131
131
  }
132
132
 
133
+ const handleItemKeyDown = (data: any) => (e: KeyboardEvent) => {
134
+ if (e.key === 'Enter' || e.key === ' ') {
135
+ e.preventDefault();
136
+ handleItemClick(data)();
137
+ }
138
+ };
139
+
133
140
 
134
141
  let picker: CommonPicker;
135
142
 
@@ -138,7 +145,7 @@
138
145
  <CommonPicker bind:this={picker} {error} {tooltip} {variant} {style} {compact} {textValue} {readonly} {placeholder} {disabled} bind:isOpen
139
146
  {theme} {value} clear={()=> {value = undefined}} {mandatory} {onfocus} {onblur}>
140
147
  {#snippet popupLayer()}
141
- <div class="uniface-options-popover" style={mh}>
148
+ <div class="uniface-options-popover" style={mh} role="listbox">
142
149
  {#if filterFunction != null}
143
150
  <div class="quick-filter-box">
144
151
  <SearchBox
@@ -163,8 +170,10 @@
163
170
  disabled={disableOptions.indexOf(op[keyField])>-1}
164
171
  onclick={handleItemClick(op)}/>
165
172
  {:else}
166
- <div class="option-item" class:disabled={disableOptions.indexOf(op[keyField])>-1} aria-hidden="true"
167
- onclick={handleItemClick(op)}>
173
+ <div class="option-item" class:disabled={disableOptions.indexOf(op[keyField])>-1}
174
+ role="option" tabindex={disableOptions.indexOf(op[keyField])>-1 ? -1 : 0}
175
+ aria-selected={String(op[keyField]) === String(value)}
176
+ onclick={handleItemClick(op)} onkeydown={handleItemKeyDown(op)}>
168
177
  <span>{op[textField]}</span>
169
178
  </div>
170
179
  {/if}
@@ -1,20 +1,42 @@
1
1
  import type CommonPickerProps from "../common_editor/CommonPickerProps";
2
- interface Props extends CommonPickerProps {
3
- emptyText?: string;
4
- value: any;
5
- options: Array<any>;
6
- keyField?: string;
7
- textField?: string;
8
- menu$height?: number;
9
- disableOptions?: Array<string>;
10
- hideOptions?: Array<string>;
11
- itemRender?: any;
12
- filterPlaceholder?: string;
13
- filterFunction?: (option: any, keyword: string) => boolean;
14
- noResultsText?: string;
2
+ declare function $$render<Option extends Record<string, any> = any>(): {
3
+ props: CommonPickerProps & {
4
+ emptyText?: string;
5
+ value: any;
6
+ options: Array<Option>;
7
+ keyField?: string;
8
+ textField?: string;
9
+ menu$height?: number;
10
+ disableOptions?: Array<string>;
11
+ hideOptions?: Array<string>;
12
+ itemRender?: any;
13
+ filterPlaceholder?: string;
14
+ filterFunction?: (option: Option, keyword: string) => boolean;
15
+ noResultsText?: string;
16
+ };
17
+ exports: {
18
+ focus: () => void;
19
+ };
20
+ bindings: "value";
21
+ slots: {};
22
+ events: {};
23
+ };
24
+ declare class __sveltets_Render<Option extends Record<string, any> = any> {
25
+ props(): ReturnType<typeof $$render<Option>>['props'];
26
+ events(): ReturnType<typeof $$render<Option>>['events'];
27
+ slots(): ReturnType<typeof $$render<Option>>['slots'];
28
+ bindings(): "value";
29
+ exports(): {
30
+ focus: () => void;
31
+ };
15
32
  }
16
- declare const OptionsSelect: import("svelte").Component<Props, {
17
- focus: () => void;
18
- }, "value">;
19
- type OptionsSelect = ReturnType<typeof OptionsSelect>;
33
+ interface $$IsomorphicComponent {
34
+ new <Option extends Record<string, any> = any>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<Option>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<Option>['props']>, ReturnType<__sveltets_Render<Option>['events']>, ReturnType<__sveltets_Render<Option>['slots']>> & {
35
+ $$bindings?: ReturnType<__sveltets_Render<Option>['bindings']>;
36
+ } & ReturnType<__sveltets_Render<Option>['exports']>;
37
+ <Option extends Record<string, any> = any>(internal: unknown, props: ReturnType<__sveltets_Render<Option>['props']> & {}): ReturnType<__sveltets_Render<Option>['exports']>;
38
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
39
+ }
40
+ declare const OptionsSelect: $$IsomorphicComponent;
41
+ type OptionsSelect<Option extends Record<string, any> = any> = InstanceType<typeof OptionsSelect<Option>>;
20
42
  export default OptionsSelect;
@@ -50,6 +50,13 @@
50
50
  e.preventDefault();
51
51
  };
52
52
 
53
+ const handleHintKeyDown = (item: string) => (e: KeyboardEvent) => {
54
+ if (e.key === 'Enter' || e.key === ' ') {
55
+ e.preventDefault();
56
+ handleHintClick(item)(e as unknown as MouseEvent);
57
+ }
58
+ };
59
+
53
60
 
54
61
 
55
62
  const clear = () => {
@@ -67,13 +74,14 @@
67
74
  <input bind:this={editor} bind:value {disabled} {readonly} {placeholder} {...eventHandlers}/>
68
75
 
69
76
  {#snippet popupLayer()}
70
- <div class="options-popover" style={mh}>
77
+ <div class="options-popover" style={mh} role="listbox">
71
78
  {#each words as word}
72
79
  <div
73
80
  class="option-item"
74
81
  style="padding-left: 12px; padding-right: 12px"
75
82
  onclick={handleHintClick(word)}
76
- aria-hidden="true"
83
+ onkeydown={handleHintKeyDown(word)}
84
+ role="option" tabindex="0" aria-selected={word === value}
77
85
  >
78
86
  <span>{word}</span>
79
87
  </div>
@@ -24,10 +24,10 @@
24
24
  </script>
25
25
 
26
26
  <div class="switch-box">
27
- <label class="switch" class:readonly class:disabled aria-hidden="true" onclick={toggleSwitch}>
28
- <input type="checkbox" bind:checked={value}>
29
- <span class="slider"></span>
30
- <span class="text">{value ? uncheckLabel : checkLabel}</span>
27
+ <label class="switch" class:readonly class:disabled>
28
+ <input type="checkbox" bind:checked={value} disabled={disabled} aria-readonly={readonly} onclick={toggleSwitch}>
29
+ <span class="slider" aria-hidden="true"></span>
30
+ <span class="text" aria-hidden="true">{value ? uncheckLabel : checkLabel}</span>
31
31
  </label>
32
32
  </div>
33
33
 
@@ -100,6 +100,13 @@
100
100
  e.preventDefault();
101
101
  };
102
102
 
103
+ const handleUnitKeyDown = (item: UnitOption) => (e: KeyboardEvent) => {
104
+ if (e.key === 'Enter' || e.key === ' ') {
105
+ e.preventDefault();
106
+ handleUnitClick(item)(e as unknown as MouseEvent);
107
+ }
108
+ };
109
+
103
110
  //
104
111
  // const handlePopupClose = () => {
105
112
  // showPopup = false;
@@ -180,10 +187,11 @@
180
187
  />
181
188
 
182
189
  {#snippet popupLayer()}
183
- <div class="options-popover" style={mh}>
190
+ <div class="options-popover" style={mh} role="listbox">
184
191
  {#each units as op}
185
192
  <div class="option-item"
186
- onclick={handleUnitClick(op)} aria-hidden="true">
193
+ onclick={handleUnitClick(op)} onkeydown={handleUnitKeyDown(op)}
194
+ role="option" tabindex="0" aria-selected={op.code === unitCode}>
187
195
  <span>{op.text ?? op.code}</span>
188
196
  </div>
189
197
  {/each}
@@ -4,6 +4,7 @@
4
4
 
5
5
  interface Props {
6
6
  type?: ButtonType;
7
+ htmlType?: 'button' | 'submit' | 'reset';
7
8
  label?: string;
8
9
  variant?: 'plain' | 'round' | '';
9
10
  disabled?: boolean;
@@ -20,6 +21,7 @@
20
21
 
21
22
  let {
22
23
  type = 'default',
24
+ htmlType = 'button',
23
25
  label = '',
24
26
  variant = '',
25
27
  disabled = false,
@@ -47,6 +49,7 @@
47
49
  <!-- autofocus is an explicit opt-in component API; consumers decide when initial focus is appropriate. -->
48
50
  <!-- svelte-ignore a11y_autofocus -->
49
51
  <button
52
+ type={htmlType}
50
53
  {style}
51
54
  class="uniface-button common-button {variant} {size} {type} {theme}"
52
55
  class:disabled={disabled}
@@ -2,6 +2,7 @@ import type { Snippet } from 'svelte';
2
2
  import type { ButtonType } from '../../types';
3
3
  interface Props {
4
4
  type?: ButtonType;
5
+ htmlType?: 'button' | 'submit' | 'reset';
5
6
  label?: string;
6
7
  variant?: 'plain' | 'round' | '';
7
8
  disabled?: boolean;
@@ -6,6 +6,7 @@
6
6
 
7
7
  interface Props {
8
8
  type?: ButtonType;
9
+ htmlType?: 'button' | 'submit' | 'reset';
9
10
  disabled?: boolean;
10
11
  size?: ButtonSize;
11
12
  style?: string;
@@ -18,6 +19,7 @@
18
19
 
19
20
  let {
20
21
  type = 'default',
22
+ htmlType = 'button',
21
23
  disabled = false,
22
24
  size = 'medium',
23
25
  style,
@@ -40,7 +42,7 @@
40
42
 
41
43
  </script>
42
44
 
43
- <button class="uniface-button icon-button {size} {type} {theme}" {style} class:disabled {disabled}
45
+ <button type={htmlType} class="uniface-button icon-button {size} {type} {theme}" {style} class:disabled {disabled}
44
46
  tabindex={disabled ? -1 : 0} data-tip={disabled ? null : tooltip} onclick={handleClick}>
45
47
  {#if children}
46
48
  {@render children()}
@@ -3,6 +3,7 @@ type ButtonType = 'default' | 'primary' | 'secondary' | 'third' | 'forth';
3
3
  type ButtonSize = 'big' | 'medium' | 'small';
4
4
  interface Props {
5
5
  type?: ButtonType;
6
+ htmlType?: 'button' | 'submit' | 'reset';
6
7
  disabled?: boolean;
7
8
  size?: ButtonSize;
8
9
  style?: string;
@@ -9,6 +9,7 @@
9
9
  size?: ButtonSize;
10
10
  label?: string;
11
11
  type?: ButtonType;
12
+ htmlType?: 'button' | 'submit' | 'reset';
12
13
  onclick?: (event: MouseEvent) => void;
13
14
  style?: string;
14
15
  theme?: string;
@@ -21,6 +22,7 @@
21
22
  size = 'medium',
22
23
  label = '',
23
24
  type = 'default',
25
+ htmlType = 'button',
24
26
  onclick = undefined,
25
27
  style = '',
26
28
  theme,
@@ -45,6 +47,7 @@
45
47
  </script>
46
48
 
47
49
  <button
50
+ type={htmlType}
48
51
  class="uniface-button text-button {size} {type} {theme}"
49
52
  {style}
50
53
  class:disabled
@@ -6,6 +6,7 @@ interface Props {
6
6
  size?: ButtonSize;
7
7
  label?: string;
8
8
  type?: ButtonType;
9
+ htmlType?: 'button' | 'submit' | 'reset';
9
10
  onclick?: (event: MouseEvent) => void;
10
11
  style?: string;
11
12
  theme?: string;
@@ -32,17 +32,34 @@
32
32
  respClick = true;
33
33
  }
34
34
  }
35
+
36
+ const isInteractive = $derived(onclick != null);
37
+
38
+ function handleKeyDown(e: KeyboardEvent) {
39
+ if (isInteractive && !disabled && (e.key === 'Enter' || e.key === ' ')) {
40
+ e.preventDefault();
41
+ handleClickEvent(e as unknown as MouseEvent);
42
+ }
43
+ }
35
44
  </script>
36
45
 
46
+ <!-- role/tabindex are only ever both set together when onclick is provided
47
+ (isInteractive); svelte-check can't verify that pairing statically. -->
48
+ <!-- svelte-ignore a11y_no_noninteractive_tabindex -->
37
49
  <div
38
50
  class="uniface-icon {theme} {className}"
39
51
  class:clickable={onclick!=null && !disabled}
40
52
  class:disabled={disabled}
41
53
  onmousedown={(event: MouseEvent) => {event.preventDefault();}}
42
54
  {style}
43
- aria-hidden="true"
55
+ role={isInteractive ? 'button' : undefined}
56
+ tabindex={isInteractive && !disabled ? 0 : undefined}
57
+ aria-disabled={isInteractive ? disabled : undefined}
58
+ aria-hidden={isInteractive ? undefined : true}
59
+ aria-label={isInteractive ? (tooltip || undefined) : undefined}
44
60
  data-tip={disabled ? null : tooltip || null}
45
61
  onclick={handleClickEvent}
62
+ onkeydown={handleKeyDown}
46
63
  >
47
64
  <i class={name}></i>
48
65
  </div>
@@ -34,13 +34,21 @@
34
34
  event.stopPropagation();
35
35
  }
36
36
 
37
+ const handleTagKeyDown = (event: KeyboardEvent) => {
38
+ if (event.key === 'Enter' || event.key === ' ') {
39
+ event.preventDefault();
40
+ ondelete?.(data?.id);
41
+ }
42
+ }
43
+
37
44
  </script>
38
45
 
39
46
  <div class="uniface-tag" {style} data-theme="{theme}">
40
47
  <div class="{size} {variant} {colorClass}" class:removable={removable}>
41
48
  <span>{text}</span>
42
49
  {#if removable}
43
- <i class="icon_google_clear uniface-remove-icon" aria-hidden="true" onclick={handleTagClick}></i>
50
+ <i class="icon_google_clear uniface-remove-icon" role="button" tabindex="0" aria-label="Remove {text}"
51
+ onclick={handleTagClick} onkeydown={handleTagKeyDown}></i>
44
52
  {/if}
45
53
  </div>
46
54
  </div>