@ticatec/uniface-element 5.0.0 → 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.
- package/README.md +29 -54
- package/README_CN.md +37 -57
- package/dist/app_layout/ClassicLayout.svelte +8 -40
- package/dist/app_layout/ColumnsLayout.svelte +3 -3
- package/dist/app_layout/HeaderLayout.svelte +4 -20
- package/dist/app_layout/RowsLayout.svelte +3 -3
- package/dist/app_layout/SidebarLayout.svelte +4 -20
- package/dist/base-calendar/CalendarBase.svelte +29 -6
- package/dist/base-calendar/CalendarBase.svelte.d.ts +4 -0
- package/dist/base-calendar/MonthPickupPanel.svelte +19 -6
- package/dist/base-calendar/MonthPickupPanel.svelte.d.ts +1 -1
- package/dist/base-calendar/MonthlyCalendar.svelte +18 -2
- package/dist/base-calendar/YearPickupPanel.svelte +24 -6
- package/dist/base-calendar/YearPickupPanel.svelte.d.ts +1 -1
- package/dist/composite/pagination_panel/PaginationPanel.svelte +2 -0
- package/dist/composite/transfer/Transfer.svelte +12 -6
- package/dist/data_display/accordion/Accordion.svelte +1 -4
- package/dist/data_display/card/CommonCardActionBar.svelte +31 -37
- package/dist/data_display/concise_data_table/Column.d.ts +6 -0
- package/dist/data_display/concise_data_table/ConciseListTable.svelte +4 -3
- package/dist/data_display/concise_data_table/DataCell.svelte +3 -3
- package/dist/data_display/list_box/ListBox.svelte +96 -23
- package/dist/data_display/list_box/ListBox.svelte.d.ts +4 -0
- package/dist/data_display/tree_view/TreeNodeView.svelte +25 -4
- package/dist/data_table/DataTable.svelte +5 -5
- package/dist/data_table/DataTable.svelte.d.ts +36 -16
- package/dist/data_table/lib/ActionsColumn.d.ts +2 -2
- package/dist/data_table/lib/DataColumn.d.ts +7 -1
- package/dist/data_table/lib/RowAction.d.ts +5 -5
- package/dist/data_table/lib/clickOutSide.js +6 -5
- package/dist/data_table/parts/FixedHeaderPanel.svelte +18 -3
- package/dist/data_table/parts/FixedRow.svelte +10 -1
- package/dist/data_table/parts/HrefCell.svelte +1 -1
- package/dist/data_table/parts/TableHeaderPanel.svelte +18 -2
- package/dist/data_table/parts/TextCell.svelte +2 -2
- package/dist/form/attachment_files/AttachmentEditor.svelte +20 -15
- package/dist/form/attachment_files/FileRender.svelte +1 -1
- package/dist/form/attachment_files/FileUploadBar.svelte +5 -2
- package/dist/form/attachment_files/FileUploadPanel.svelte +11 -73
- package/dist/form/cascade_options_select/CascadeOptionSelect.svelte +10 -2
- package/dist/form/cascade_options_select/OptionsBox.svelte +48 -2
- package/dist/form/checkbox/CheckBox.svelte +2 -7
- package/dist/form/color_picker/ColorPicker.svelte +150 -35
- package/dist/form/color_picker/ColorPicker.svelte.d.ts +7 -25
- package/dist/form/color_picker/ColorPickerPanel.svelte +23 -20
- package/dist/form/color_picker/ColorPickerPanel.svelte.d.ts +5 -18
- package/dist/form/color_picker/README.md +14 -7
- package/dist/form/color_picker/README_CN.md +14 -7
- package/dist/form/common_editor/CommonEditor.svelte +18 -4
- package/dist/form/common_editor/CommonPicker.svelte +14 -10
- package/dist/form/common_editor/CommonPopupEditor.svelte +8 -1
- package/dist/form/common_range_editor/CommonRangeEditor.svelte +11 -2
- package/dist/form/date_picker/DatePicker.svelte +1 -1
- package/dist/form/date_picker/DateTimePicker.svelte +1 -1
- package/dist/form/date_picker/ScrollBar.svelte +20 -12
- package/dist/form/date_picker/ScrollBar.svelte.d.ts +4 -18
- package/dist/form/date_range/DateRangeEditor.svelte +11 -3
- package/dist/form/group_box/group-check-box/GroupCheckBox.svelte +6 -1
- package/dist/form/group_box/group-radio-box/GroupRadioBox.svelte +6 -1
- package/dist/form/image-files/ImageFilesField.svelte +51 -7
- package/dist/form/image-files/ImagePreview.svelte +23 -9
- package/dist/form/image-files/ImageRender.svelte +69 -11
- package/dist/form/input_options_select/InputOptionsSelect.svelte +10 -2
- package/dist/form/lookup_editor/LookupEditor.svelte +9 -2
- package/dist/form/memo_editor/MemoEditor.svelte +2 -2
- package/dist/form/number_editor/NumberEditor.svelte +2 -2
- package/dist/form/options_multi_select/OptionsMultiSelect.svelte +20 -12
- package/dist/form/options_select/OptionsSelect.svelte +15 -6
- package/dist/form/options_select/OptionsSelect.svelte.d.ts +39 -17
- package/dist/form/prompts_text_editor/PromptsTextEditor.svelte +10 -2
- package/dist/form/radio_button/RadioButton.svelte +2 -8
- package/dist/form/switch/Switch.svelte +4 -4
- package/dist/form/text_editor/TextEditor.svelte +2 -2
- package/dist/form/unit-number-editor/UnitNumberEditor.svelte +10 -2
- package/dist/general/button/Button.svelte +5 -0
- package/dist/general/button/Button.svelte.d.ts +1 -0
- package/dist/general/button/IconButton.svelte +3 -1
- package/dist/general/button/IconButton.svelte.d.ts +1 -0
- package/dist/general/button/TextButton.svelte +3 -0
- package/dist/general/button/TextButton.svelte.d.ts +1 -0
- package/dist/general/icon/Icon.svelte +18 -1
- package/dist/general/split/Split.svelte +24 -4
- package/dist/general/tag/Tag.svelte +9 -1
- package/dist/navigation/nav_menu/MenuItem.d.ts +4 -2
- package/dist/navigation/nav_menu/NavigatorMenu.svelte +157 -34
- package/dist/navigation/nav_menu/NavigatorMenu.svelte.d.ts +2 -3
- package/dist/navigation/nav_menu/NavigatorMenuItem.svelte +25 -13
- package/dist/navigation/nav_menu/NavigatorMenuItem.svelte.d.ts +3 -3
- package/dist/navigation/navigator/Navigator.svelte +17 -17
- package/dist/navigation/page-stack/PageStack.svelte +160 -0
- package/dist/navigation/page-stack/PageStack.svelte.d.ts +24 -0
- package/dist/navigation/page-stack/PageStackContext.d.ts +25 -0
- package/dist/navigation/page-stack/PageStackContext.js +12 -0
- package/dist/navigation/page-stack/PageStackFrame.svelte +24 -0
- package/dist/navigation/page-stack/PageStackFrame.svelte.d.ts +11 -0
- package/dist/navigation/page-stack/README.md +154 -0
- package/dist/navigation/page-stack/README_CN.md +154 -0
- package/dist/navigation/page-stack/index.d.ts +6 -0
- package/dist/navigation/page-stack/index.js +4 -0
- package/dist/navigation/pagination/Pagination.svelte +114 -14
- package/dist/navigation/progress_step_bar/ProgressStepBlock.svelte +1 -5
- package/dist/navigation/tabs/Tabs.svelte +42 -10
- package/dist/navigation/tabs/Tabs.svelte.d.ts +2 -2
- package/dist/overlay/common/FloatingPanel.svelte +3 -17
- package/dist/overlay/common/FullscreenOverlay.svelte +27 -3
- package/dist/overlay/common/FullscreenOverlay.svelte.d.ts +6 -27
- package/dist/overlay/common/ModalPopover.svelte +18 -2
- package/dist/overlay/common/Popover.svelte +61 -57
- package/dist/overlay/common/Popover.svelte.d.ts +1 -5
- package/dist/overlay/common/escapeClose.d.ts +28 -0
- package/dist/overlay/common/escapeClose.js +47 -0
- package/dist/overlay/common/focusTrap.d.ts +8 -0
- package/dist/overlay/common/focusTrap.js +83 -0
- package/dist/overlay/common/mountSingleton.d.ts +27 -0
- package/dist/overlay/common/mountSingleton.js +45 -0
- package/dist/overlay/common/outsideClick.d.ts +28 -0
- package/dist/overlay/common/outsideClick.js +20 -0
- package/dist/overlay/common/scrollLock.d.ts +8 -0
- package/dist/overlay/common/scrollLock.js +49 -0
- package/dist/overlay/common/uniface-utils.js +0 -1
- package/dist/overlay/context-menu/ContextMenu.svelte.js +2 -15
- package/dist/overlay/context-menu/ContextMenuPanel.svelte +27 -3
- package/dist/overlay/dialog/Dialog.svelte +48 -32
- package/dist/overlay/dialog/DialogManager.svelte.js +7 -9
- package/dist/overlay/dialog/DialogWrapper.svelte +5 -2
- package/dist/overlay/drawer/Drawer.svelte +30 -3
- package/dist/overlay/indicator/Indicator.svelte.js +2 -15
- package/dist/overlay/indicator/IndicatorPanel.svelte +4 -1
- package/dist/overlay/message-box/MessageBox.svelte.js +2 -15
- package/dist/overlay/message-box/MessageBoxPanel.svelte +19 -3
- package/dist/overlay/toast/Toast.svelte.js +2 -15
- package/dist/overlay/toast/ToastPanel.svelte +1 -1
- package/dist/overlay/tooltip/Tooltip.svelte +1 -1
- package/dist/ticatec-uniface-web.css +128 -13
- package/dist/types.d.ts +4 -3
- package/dist/utils/prefixFilter.d.ts +3 -3
- package/dist/utils/prefixFilter.js +3 -5
- package/docs/components/README.md +133 -0
- package/docs/components/accordion/README.md +60 -0
- package/docs/components/accordion/example.svelte +7 -0
- package/docs/components/action-bar/README.md +114 -0
- package/docs/components/action-bar/example.svelte +7 -0
- package/docs/components/app-top-bar/README.md +60 -0
- package/docs/components/app-top-bar/example.svelte +9 -0
- package/docs/components/attachment-files/README.md +332 -0
- package/docs/components/attachment-files/example.svelte +16 -0
- package/docs/components/box/README.md +63 -0
- package/docs/components/box/example.svelte +10 -0
- package/docs/components/breadcrumbs/README.md +86 -0
- package/docs/components/breadcrumbs/example.svelte +11 -0
- package/docs/components/button/README.md +103 -0
- package/docs/components/button/example.svelte +10 -0
- package/docs/components/card/README.md +113 -0
- package/docs/components/card/example.svelte +10 -0
- package/docs/components/cascade-options-select/README.md +162 -0
- package/docs/components/cascade-options-select/example.svelte +18 -0
- package/docs/components/checkbox/README.md +103 -0
- package/docs/components/checkbox/example.svelte +15 -0
- package/docs/components/classic-layout/README.md +76 -0
- package/docs/components/classic-layout/example.svelte +16 -0
- package/docs/components/color-picker/README.md +132 -0
- package/docs/components/color-picker/example.svelte +16 -0
- package/docs/components/columns-layout/README.md +70 -0
- package/docs/components/columns-layout/example.svelte +12 -0
- package/docs/components/common-dialog/README.md +109 -0
- package/docs/components/common-dialog/example.svelte +12 -0
- package/docs/components/concise-data-table/README.md +307 -0
- package/docs/components/concise-data-table/example.svelte +16 -0
- package/docs/components/context-menu/README.md +99 -0
- package/docs/components/context-menu/example.svelte +10 -0
- package/docs/components/criteria-field/README.md +69 -0
- package/docs/components/criteria-field/example.svelte +9 -0
- package/docs/components/data-table/README.md +365 -0
- package/docs/components/data-table/example.svelte +23 -0
- package/docs/components/date-picker/README.md +136 -0
- package/docs/components/date-picker/example.svelte +16 -0
- package/docs/components/date-range/README.md +122 -0
- package/docs/components/date-range/example.svelte +15 -0
- package/docs/components/date-time-picker/README.md +142 -0
- package/docs/components/date-time-picker/example.svelte +16 -0
- package/docs/components/dialog/README.md +174 -0
- package/docs/components/dialog/example.svelte +13 -0
- package/docs/components/dialog-board/README.md +41 -0
- package/docs/components/dialog-board/example.svelte +5 -0
- package/docs/components/drawer/README.md +70 -0
- package/docs/components/drawer/example.svelte +12 -0
- package/docs/components/flex-form/README.md +55 -0
- package/docs/components/flex-form/example.svelte +7 -0
- package/docs/components/flex-row-form/README.md +56 -0
- package/docs/components/flex-row-form/example.svelte +7 -0
- package/docs/components/form-field/README.md +84 -0
- package/docs/components/form-field/example.svelte +10 -0
- package/docs/components/full-screen-overlay/README.md +66 -0
- package/docs/components/full-screen-overlay/example.svelte +11 -0
- package/docs/components/grid-form/README.md +75 -0
- package/docs/components/grid-form/example.svelte +9 -0
- package/docs/components/group-check-box/README.md +147 -0
- package/docs/components/group-check-box/example.svelte +21 -0
- package/docs/components/group-radio-box/README.md +144 -0
- package/docs/components/group-radio-box/example.svelte +21 -0
- package/docs/components/header-layout/README.md +65 -0
- package/docs/components/header-layout/example.svelte +12 -0
- package/docs/components/icon/README.md +87 -0
- package/docs/components/icon/example.svelte +9 -0
- package/docs/components/icon-button/README.md +91 -0
- package/docs/components/icon-button/example.svelte +10 -0
- package/docs/components/image-files/README.md +174 -0
- package/docs/components/image-files/example.svelte +19 -0
- package/docs/components/indicator/README.md +53 -0
- package/docs/components/indicator/example.svelte +14 -0
- package/docs/components/input-options-select/README.md +163 -0
- package/docs/components/input-options-select/example.svelte +16 -0
- package/docs/components/list-box/ListItem.svelte +14 -0
- package/docs/components/list-box/README.md +221 -0
- package/docs/components/list-box/example.svelte +61 -0
- package/docs/components/lookup-editor/README.md +137 -0
- package/docs/components/lookup-editor/example.svelte +16 -0
- package/docs/components/memo-editor/README.md +143 -0
- package/docs/components/memo-editor/example.svelte +16 -0
- package/docs/components/message-box/README.md +68 -0
- package/docs/components/message-box/example.svelte +10 -0
- package/docs/components/navigator/README.md +75 -0
- package/docs/components/navigator/example.svelte +13 -0
- package/docs/components/navigator-menu/README.md +113 -0
- package/docs/components/navigator-menu/example.svelte +10 -0
- package/docs/components/number-editor/README.md +144 -0
- package/docs/components/number-editor/example.svelte +16 -0
- package/docs/components/number-range/README.md +116 -0
- package/docs/components/number-range/example.svelte +15 -0
- package/docs/components/options-multi-select/README.md +161 -0
- package/docs/components/options-multi-select/example.svelte +20 -0
- package/docs/components/options-select/README.md +160 -0
- package/docs/components/options-select/example.svelte +21 -0
- package/docs/components/page/README.md +77 -0
- package/docs/components/page/example.svelte +10 -0
- package/docs/components/pagination/README.md +88 -0
- package/docs/components/pagination/example.svelte +10 -0
- package/docs/components/pagination-panel/README.md +120 -0
- package/docs/components/pagination-panel/example.svelte +16 -0
- package/docs/components/popup-hint/README.md +44 -0
- package/docs/components/popup-hint/example.svelte +5 -0
- package/docs/components/progress-bar/README.md +64 -0
- package/docs/components/progress-bar/example.svelte +8 -0
- package/docs/components/progress-step-bar/README.md +93 -0
- package/docs/components/progress-step-bar/example.svelte +7 -0
- package/docs/components/prompts-text-editor/README.md +146 -0
- package/docs/components/prompts-text-editor/example.svelte +17 -0
- package/docs/components/radio-button/README.md +121 -0
- package/docs/components/radio-button/example.svelte +18 -0
- package/docs/components/rows-layout/README.md +70 -0
- package/docs/components/rows-layout/example.svelte +12 -0
- package/docs/components/search-box/README.md +136 -0
- package/docs/components/search-box/example.svelte +16 -0
- package/docs/components/separator/README.md +44 -0
- package/docs/components/separator/example.svelte +7 -0
- package/docs/components/sidebar-layout/README.md +65 -0
- package/docs/components/sidebar-layout/example.svelte +12 -0
- package/docs/components/split/README.md +48 -0
- package/docs/components/split/example.svelte +8 -0
- package/docs/components/switch/README.md +77 -0
- package/docs/components/switch/example.svelte +11 -0
- package/docs/components/tabs/README.md +127 -0
- package/docs/components/tabs/example.svelte +22 -0
- package/docs/components/tag/README.md +63 -0
- package/docs/components/tag/example.svelte +8 -0
- package/docs/components/text-button/README.md +90 -0
- package/docs/components/text-button/example.svelte +9 -0
- package/docs/components/text-editor/README.md +147 -0
- package/docs/components/text-editor/example.svelte +16 -0
- package/docs/components/time-editor/README.md +130 -0
- package/docs/components/time-editor/example.svelte +16 -0
- package/docs/components/toast/README.md +52 -0
- package/docs/components/toast/example.svelte +9 -0
- package/docs/components/tooltip/README.md +44 -0
- package/docs/components/tooltip/example.svelte +5 -0
- package/docs/components/transfer/README.md +109 -0
- package/docs/components/transfer/example.svelte +13 -0
- package/docs/components/tree-view/README.md +163 -0
- package/docs/components/tree-view/example.svelte +26 -0
- package/docs/components/unit-number-editor/README.md +192 -0
- package/docs/components/unit-number-editor/example.svelte +18 -0
- package/package.json +15 -7
|
@@ -23,13 +23,59 @@
|
|
|
23
23
|
selectedItem = item;
|
|
24
24
|
onSelect(item);
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
const handleItemKeyDown = (item: any) => (e: KeyboardEvent) => {
|
|
28
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
29
|
+
e.preventDefault();
|
|
30
|
+
handleItemClick(item)(e as unknown as MouseEvent);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
26
33
|
</script>
|
|
27
34
|
|
|
28
|
-
<div class="cascade-column" style={box$style}>
|
|
35
|
+
<div class="cascade-column" style={box$style} role="listbox">
|
|
29
36
|
{#each options as op (op[keyField])}
|
|
30
37
|
<div class="option-item" class:selected={op[keyField] === (selectedItem ?? {})[keyField]}
|
|
31
|
-
|
|
38
|
+
role="option" tabindex="0" aria-selected={op[keyField] === (selectedItem ?? {})[keyField]}
|
|
39
|
+
onclick={handleItemClick(op)} onkeydown={handleItemKeyDown(op)}>
|
|
32
40
|
<span>{op[textField]}</span>
|
|
33
41
|
</div>
|
|
34
42
|
{/each}
|
|
35
43
|
</div>
|
|
44
|
+
|
|
45
|
+
<style>
|
|
46
|
+
/* Base sizing so a column looks correct even when the consumer doesn't
|
|
47
|
+
pass box$style — previously there was no default at all, so columns
|
|
48
|
+
had no width/overflow handling and collapsed unpredictably inside the
|
|
49
|
+
popover's flex row. box$style (inline style, applied after these
|
|
50
|
+
rules) can still override any of this per column. */
|
|
51
|
+
.cascade-column {
|
|
52
|
+
flex: 0 0 auto;
|
|
53
|
+
width: 140px;
|
|
54
|
+
height: 100%;
|
|
55
|
+
box-sizing: border-box;
|
|
56
|
+
overflow-y: auto;
|
|
57
|
+
overflow-x: hidden;
|
|
58
|
+
border-right: 1px solid var(--uniface-color-border-secondary);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.cascade-column:last-child {
|
|
62
|
+
border-right: none;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.option-item {
|
|
66
|
+
padding: 6px 12px;
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
overflow: hidden;
|
|
69
|
+
text-overflow: ellipsis;
|
|
70
|
+
white-space: nowrap;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.option-item:hover {
|
|
74
|
+
background-color: var(--uniface-popover-item-color-surface-hover);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.option-item.selected {
|
|
78
|
+
background-color: var(--uniface-popover-item-color-surface-active);
|
|
79
|
+
color: var(--uniface-popover-item-color-active);
|
|
80
|
+
}
|
|
81
|
+
</style>
|
|
@@ -123,6 +123,7 @@
|
|
|
123
123
|
--disabled-inner: var(--uniface-checkbox-checkmark-color-disabled);
|
|
124
124
|
-webkit-appearance: none;
|
|
125
125
|
-moz-appearance: none;
|
|
126
|
+
appearance: none;
|
|
126
127
|
height: var(--uniface-checkbox-size);
|
|
127
128
|
outline: none;
|
|
128
129
|
display: inline-block;
|
|
@@ -191,12 +192,6 @@
|
|
|
191
192
|
--o: 1;
|
|
192
193
|
--r: var(--uniface-checkbox-check-rotation);
|
|
193
194
|
}
|
|
194
|
-
.uniface-checkbox input[type=checkbox] + label {
|
|
195
|
-
display: inline-block;
|
|
196
|
-
vertical-align: middle;
|
|
197
|
-
cursor: pointer;
|
|
198
|
-
margin-left: 4px;
|
|
199
|
-
}
|
|
200
195
|
.uniface-checkbox.compact {
|
|
201
196
|
padding: 0;
|
|
202
197
|
color: var(--uniface-checkbox-text-color);
|
|
@@ -224,4 +219,4 @@
|
|
|
224
219
|
.uniface-checkbox *::before,
|
|
225
220
|
.uniface-checkbox *::after {
|
|
226
221
|
box-sizing: inherit;
|
|
227
|
-
}</style>
|
|
222
|
+
}</style>
|
|
@@ -1,58 +1,173 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
import type {OnChangeHandler} from "../../types";
|
|
5
3
|
import CommonPicker from "../common_editor/CommonPicker.svelte";
|
|
4
|
+
import type CommonFieldProps from "../common_editor/CommonFieldProps";
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
interface Props extends CommonFieldProps {
|
|
7
|
+
value?: string;
|
|
8
|
+
}
|
|
8
9
|
|
|
9
|
-
//
|
|
10
|
-
//
|
|
10
|
+
// The manually-typed value must resolve to exactly #RRGGBB. An 8-digit #RRGGBBAA
|
|
11
|
+
// form was supported briefly, but <input type="color"> has no concept of alpha —
|
|
12
|
+
// the swatch always showed just the RGB portion and nothing in the UI ever
|
|
13
|
+
// rendered the transparency, so the last 2 digits had no visible effect. Dropped
|
|
14
|
+
// rather than half-implemented; revisit with a real alpha-aware swatch (checkered
|
|
15
|
+
// background + rgba preview) if this is needed later.
|
|
16
|
+
const HEX_PATTERN = /^#[0-9a-fA-F]{6}$/;
|
|
17
|
+
const DEFAULT_SWATCH = '#000000';
|
|
18
|
+
|
|
19
|
+
// CommonPicker always renders its own internal <input> in the non-readonly branch,
|
|
20
|
+
// even when a `children` snippet is also supplied — it doesn't apply the same
|
|
21
|
+
// "children replaces the default input" rule that its readonly branch does. Every
|
|
22
|
+
// other consumer works around this by never passing `children` in the first place
|
|
23
|
+
// (DatePicker, OptionsSelect...) except OptionsMultiSelect, which needs custom
|
|
24
|
+
// content (its tag list) the same way ColorPicker needs its swatch+hex layout —
|
|
25
|
+
// it hides CommonPicker's own input via `input$style` (shrink to 1x1, transparent,
|
|
26
|
+
// click-through) so only the custom children are visible. Same fix here: without
|
|
27
|
+
// this, edit mode showed CommonPicker's own empty input fighting for space with our
|
|
28
|
+
// swatch, while readonly mode (which only renders `children`) looked correct.
|
|
29
|
+
const HIDDEN_INTERNAL_INPUT_STYLE = 'position: absolute; left: 0; top: 0; width: 1px; height: 1px; opacity: 0; pointer-events: none';
|
|
30
|
+
|
|
31
|
+
let {
|
|
32
|
+
variant,
|
|
33
|
+
theme,
|
|
34
|
+
disabled = false,
|
|
35
|
+
readonly = false,
|
|
36
|
+
compact = false,
|
|
37
|
+
value = $bindable<string | undefined>("#000000"),
|
|
38
|
+
style,
|
|
39
|
+
placeholder,
|
|
40
|
+
error,
|
|
41
|
+
tooltip,
|
|
42
|
+
onchange,
|
|
43
|
+
onfocus,
|
|
44
|
+
onblur
|
|
45
|
+
}: Props = $props();
|
|
46
|
+
|
|
47
|
+
let editor: HTMLInputElement | undefined = $state();
|
|
48
|
+
let textInput: HTMLInputElement | undefined = $state();
|
|
49
|
+
|
|
50
|
+
// Editing buffer for the manual hex field, kept separate from `value` so the user
|
|
51
|
+
// can type through transient/incomplete states (e.g. "#3b8") without every
|
|
52
|
+
// keystroke being validated against the full #RRGGBB format — validation only
|
|
53
|
+
// happens on commit (blur / Enter).
|
|
54
|
+
let textValue = $state(value ?? '');
|
|
55
|
+
|
|
56
|
+
$effect(() => {
|
|
57
|
+
textValue = value ?? '';
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
let swatchValue = $derived(value && HEX_PATTERN.test(value) ? value : DEFAULT_SWATCH);
|
|
61
|
+
|
|
62
|
+
export const focus = () => {
|
|
63
|
+
editor?.focus();
|
|
64
|
+
}
|
|
11
65
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export let value: any = "#ff3e00";
|
|
17
|
-
export let style: string = '';
|
|
18
|
-
export let onChange: OnChangeHandler<any> = null as unknown as OnChangeHandler<any>;
|
|
66
|
+
const clean = () => {
|
|
67
|
+
value = undefined;
|
|
68
|
+
onchange?.(undefined);
|
|
69
|
+
}
|
|
19
70
|
|
|
71
|
+
const handleActionIconClick = () => {
|
|
72
|
+
if (!readonly && !disabled) {
|
|
73
|
+
editor?.click();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
20
76
|
|
|
21
|
-
|
|
77
|
+
const handleSwatchChange = (event: Event) => {
|
|
78
|
+
const newValue = (event.target as HTMLInputElement).value;
|
|
79
|
+
value = newValue;
|
|
80
|
+
onchange?.(newValue);
|
|
81
|
+
}
|
|
22
82
|
|
|
23
|
-
|
|
24
|
-
|
|
83
|
+
// The native color picker dialog opens on `click`, and preventing the default
|
|
84
|
+
// action here blocks it — this is the only reliable way to make the swatch
|
|
85
|
+
// non-interactive for `readonly`, since <input type="color"> ignores the
|
|
86
|
+
// `readonly` attribute entirely. Using the native `disabled` attribute instead
|
|
87
|
+
// would work too, but it also greys the swatch out, which conflates readonly
|
|
88
|
+
// with disabled (see the component README: readonly stays fully visible,
|
|
89
|
+
// disabled is dimmed).
|
|
90
|
+
const handleColorInputClick = (event: MouseEvent) => {
|
|
91
|
+
if (readonly) {
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
}
|
|
25
94
|
}
|
|
26
95
|
|
|
27
|
-
|
|
96
|
+
const handleColorInputKeydown = (event: KeyboardEvent) => {
|
|
97
|
+
if (readonly && (event.key === 'Enter' || event.key === ' ')) {
|
|
98
|
+
event.preventDefault();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
28
101
|
|
|
29
|
-
const
|
|
30
|
-
|
|
102
|
+
const commitTextValue = () => {
|
|
103
|
+
let candidate = textValue.trim();
|
|
104
|
+
if (candidate && !candidate.startsWith('#')) {
|
|
105
|
+
candidate = `#${candidate}`;
|
|
106
|
+
}
|
|
107
|
+
if (HEX_PATTERN.test(candidate)) {
|
|
108
|
+
textValue = candidate;
|
|
109
|
+
if (candidate !== value) {
|
|
110
|
+
value = candidate;
|
|
111
|
+
onchange?.(candidate);
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
// Doesn't resolve to a valid #RRGGBB value on commit — revert to the last
|
|
115
|
+
// known-good value rather than accepting a malformed color.
|
|
116
|
+
textValue = value ?? '';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Only '#' and hex digits are allowed while typing; the exact length requirement
|
|
121
|
+
// is enforced separately on commit (see commitTextValue), since rejecting
|
|
122
|
+
// incomplete input on every keystroke would make it impossible to type a value
|
|
123
|
+
// character by character.
|
|
124
|
+
const handleTextKeydown = (event: KeyboardEvent) => {
|
|
125
|
+
const allowKeys = ['Backspace', 'Delete', 'Tab', 'ArrowLeft', 'ArrowRight', 'Home', 'End'];
|
|
126
|
+
if (allowKeys.includes(event.key) || event.metaKey || event.ctrlKey) return;
|
|
127
|
+
if (event.key === 'Enter') {
|
|
128
|
+
event.preventDefault();
|
|
129
|
+
textInput?.blur();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (event.key === 'Escape') {
|
|
133
|
+
textValue = value ?? '';
|
|
134
|
+
textInput?.blur();
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (!/^[0-9a-fA-F#]$/.test(event.key)) {
|
|
138
|
+
event.preventDefault();
|
|
139
|
+
}
|
|
31
140
|
}
|
|
32
141
|
|
|
33
|
-
const
|
|
34
|
-
|
|
142
|
+
const handleTextPaste = (event: ClipboardEvent) => {
|
|
143
|
+
const pasted = event.clipboardData?.getData('text') ?? '';
|
|
144
|
+
if (/[^0-9a-fA-F#]/.test(pasted)) {
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
}
|
|
35
147
|
}
|
|
36
148
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
149
|
+
// Defense in depth against anything that bypasses handleTextKeydown (IME, mobile
|
|
150
|
+
// virtual keyboards, drag-and-drop text) — strip disallowed characters and cap at
|
|
151
|
+
// one leading '#' plus 6 hex digits.
|
|
152
|
+
const handleTextInput = () => {
|
|
153
|
+
const hasHash = textValue.startsWith('#');
|
|
154
|
+
const hexOnly = textValue.replace(/#/g, '').replace(/[^0-9a-fA-F]/g, '').slice(0, 6);
|
|
155
|
+
const sanitized = (hasHash ? '#' : '') + hexOnly;
|
|
156
|
+
if (sanitized !== textValue) {
|
|
157
|
+
textValue = sanitized;
|
|
158
|
+
}
|
|
45
159
|
}
|
|
46
160
|
|
|
47
161
|
</script>
|
|
48
162
|
|
|
49
|
-
<CommonPicker {variant} {style} {compact} className="multiple" iconName="icon_google_color_lens"
|
|
50
|
-
autoFit clear={clean} textValue={value} {readonly} {disabled} iconClickHandler={handleActionIconClick}
|
|
51
|
-
|
|
163
|
+
<CommonPicker {variant} {style} {theme} {error} {tooltip} {compact} {placeholder} className="multiple" iconName="icon_google_color_lens"
|
|
164
|
+
autoFit clear={clean} textValue={value} {readonly} {disabled} {onfocus} {onblur} iconClickHandler={handleActionIconClick}
|
|
165
|
+
input$style={HIDDEN_INTERNAL_INPUT_STYLE}>
|
|
52
166
|
<div style="width: 100%; display: flex; overflow: hidden; flex-direction: row; align-items: center; height: 100%; gap: 8px">
|
|
53
|
-
<input bind:this={editor} style="flex: 0 0 auto; width: 40%; height: 80%; border-radius: 8px;" type="color"
|
|
54
|
-
|
|
167
|
+
<input bind:this={editor} style="flex: 0 0 auto; width: 40%; height: 80%; border-radius: 8px;" type="color" value={swatchValue} {disabled}
|
|
168
|
+
tabindex={readonly ? -1 : 0} onclick={handleColorInputClick} onkeydown={handleColorInputKeydown} onchange={handleSwatchChange}/>
|
|
169
|
+
<input bind:this={textInput} style="flex: 0 0 auto; width: 50%; text-align: center" class="text-editor" bind:value={textValue}
|
|
170
|
+
readonly={readonly} {disabled} {placeholder} maxlength="7" spellcheck="false" autocomplete="off"
|
|
171
|
+
onblur={commitTextValue} onkeydown={handleTextKeydown} onpaste={handleTextPaste} oninput={handleTextInput}/>
|
|
55
172
|
</div>
|
|
56
|
-
|
|
57
|
-
|
|
58
173
|
</CommonPicker>
|
|
@@ -1,27 +1,9 @@
|
|
|
1
|
-
import type
|
|
2
|
-
interface
|
|
3
|
-
|
|
4
|
-
$$bindings?: Bindings;
|
|
5
|
-
} & Exports;
|
|
6
|
-
(internal: unknown, props: Props & {
|
|
7
|
-
$$events?: Events;
|
|
8
|
-
$$slots?: Slots;
|
|
9
|
-
}): Exports & {
|
|
10
|
-
$set?: any;
|
|
11
|
-
$on?: any;
|
|
12
|
-
};
|
|
13
|
-
z_$$bindings?: Bindings;
|
|
1
|
+
import type CommonFieldProps from "../common_editor/CommonFieldProps";
|
|
2
|
+
interface Props extends CommonFieldProps {
|
|
3
|
+
value?: string;
|
|
14
4
|
}
|
|
15
|
-
declare const ColorPicker:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
compact?: boolean;
|
|
20
|
-
value?: any;
|
|
21
|
-
style?: string;
|
|
22
|
-
onChange?: OnChangeHandler<any>;
|
|
23
|
-
}, {
|
|
24
|
-
[evt: string]: CustomEvent<any>;
|
|
25
|
-
}, {}, {}, string>;
|
|
26
|
-
type ColorPicker = InstanceType<typeof ColorPicker>;
|
|
5
|
+
declare const ColorPicker: import("svelte").Component<Props, {
|
|
6
|
+
focus: () => void;
|
|
7
|
+
}, "value">;
|
|
8
|
+
type ColorPicker = ReturnType<typeof ColorPicker>;
|
|
27
9
|
export default ColorPicker;
|
|
@@ -3,14 +3,25 @@
|
|
|
3
3
|
|
|
4
4
|
import i18nRes from "../../i18nRes";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
interface Props {
|
|
7
|
+
initialColor?: string;
|
|
8
|
+
showHex?: boolean;
|
|
9
|
+
showRgb?: boolean;
|
|
10
|
+
swatches?: Array<any>;
|
|
11
|
+
onchange?: (color: string) => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let {initialColor = "#ffffff", showHex = true, showRgb = false, swatches = [], onchange}: Props = $props();
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
// Neutral initial value + effect-driven sync (rather than $state(initialColor))
|
|
17
|
+
// avoids implying initialColor is captured only once; the effect keeps
|
|
18
|
+
// selectedColor in sync whenever the prop changes later.
|
|
19
|
+
let selectedColor = $state('#ffffff');
|
|
20
|
+
let rgbValues = $derived(hexToRgb(selectedColor));
|
|
13
21
|
|
|
22
|
+
$effect(() => {
|
|
23
|
+
selectedColor = initialColor;
|
|
24
|
+
});
|
|
14
25
|
|
|
15
26
|
// Convert hex to RGB
|
|
16
27
|
function hexToRgb(hex: string) {
|
|
@@ -22,24 +33,15 @@
|
|
|
22
33
|
} : { r: 0, g: 0, b: 0 };
|
|
23
34
|
}
|
|
24
35
|
|
|
25
|
-
//
|
|
36
|
+
// selectedColor is already updated by bind:value before this fires
|
|
26
37
|
function handleColorChange(event: Event) {
|
|
27
|
-
selectedColor
|
|
28
|
-
rgbValues = hexToRgb(selectedColor);
|
|
29
|
-
// dispatch('change', {
|
|
30
|
-
// hex: selectedColor,
|
|
31
|
-
// rgb: rgbValues
|
|
32
|
-
// });
|
|
38
|
+
onchange?.(selectedColor);
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
// Select a swatch
|
|
36
42
|
function selectSwatch(color: any) {
|
|
37
43
|
selectedColor = color;
|
|
38
|
-
|
|
39
|
-
// dispatch('change', {
|
|
40
|
-
// hex: selectedColor,
|
|
41
|
-
// rgb: rgbValues
|
|
42
|
-
// });
|
|
44
|
+
onchange?.(selectedColor);
|
|
43
45
|
}
|
|
44
46
|
</script>
|
|
45
47
|
|
|
@@ -53,7 +55,7 @@
|
|
|
53
55
|
id="color-input"
|
|
54
56
|
type="color"
|
|
55
57
|
bind:value={selectedColor}
|
|
56
|
-
|
|
58
|
+
onchange={handleColorChange}
|
|
57
59
|
/>
|
|
58
60
|
<div
|
|
59
61
|
class="color-preview"
|
|
@@ -77,9 +79,10 @@
|
|
|
77
79
|
<div class="swatches">
|
|
78
80
|
{#each swatches as swatch}
|
|
79
81
|
<button
|
|
82
|
+
type="button"
|
|
80
83
|
class="swatch"
|
|
81
84
|
style="background-color: {swatch};"
|
|
82
|
-
|
|
85
|
+
onclick={() => selectSwatch(swatch)}
|
|
83
86
|
aria-label={`Select color ${swatch}`}
|
|
84
87
|
class:selected={selectedColor === swatch}
|
|
85
88
|
></button>
|
|
@@ -1,23 +1,10 @@
|
|
|
1
|
-
interface
|
|
2
|
-
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
-
$$bindings?: Bindings;
|
|
4
|
-
} & Exports;
|
|
5
|
-
(internal: unknown, props: Props & {
|
|
6
|
-
$$events?: Events;
|
|
7
|
-
$$slots?: Slots;
|
|
8
|
-
}): Exports & {
|
|
9
|
-
$set?: any;
|
|
10
|
-
$on?: any;
|
|
11
|
-
};
|
|
12
|
-
z_$$bindings?: Bindings;
|
|
13
|
-
}
|
|
14
|
-
declare const ColorPickerPanel: $$__sveltets_2_IsomorphicComponent<{
|
|
1
|
+
interface Props {
|
|
15
2
|
initialColor?: string;
|
|
16
3
|
showHex?: boolean;
|
|
17
4
|
showRgb?: boolean;
|
|
18
5
|
swatches?: Array<any>;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
type ColorPickerPanel =
|
|
6
|
+
onchange?: (color: string) => void;
|
|
7
|
+
}
|
|
8
|
+
declare const ColorPickerPanel: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type ColorPickerPanel = ReturnType<typeof ColorPickerPanel>;
|
|
23
10
|
export default ColorPickerPanel;
|
|
@@ -40,7 +40,7 @@ import ColorPicker from "@ticatec/uniface-element/ColorPicker";
|
|
|
40
40
|
|
|
41
41
|
| Prop | Type | Default | Description |
|
|
42
42
|
|------|------|---------|-------------|
|
|
43
|
-
| `value` | `string` (bindable) | `"#000000"` | The selected color in hex format (e.g., `#3b82f6`). `bind:value={...}` for two-way binding. |
|
|
43
|
+
| `value` | `string` (bindable) | `"#000000"` | The selected color in `#RRGGBB` hex format (e.g., `#3b82f6`). `bind:value={...}` for two-way binding. |
|
|
44
44
|
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | Visual style variant. |
|
|
45
45
|
| `compact` | `boolean` | `false` | Dense layout for table cells and inline forms. |
|
|
46
46
|
| `disabled` | `boolean` | `false` | Fully disabled — the color picker is non-interactive. |
|
|
@@ -263,18 +263,25 @@ import ColorPicker from "@ticatec/uniface-element/ColorPicker";
|
|
|
263
263
|
|
|
264
264
|
## Behavior Notes
|
|
265
265
|
|
|
266
|
-
### Native color input
|
|
266
|
+
### Native color input + editable hex field
|
|
267
267
|
|
|
268
|
-
The component
|
|
268
|
+
The component shows two parts side by side: a native `<input type="color">` swatch (opens the browser's built-in color picker) and a text field showing the hex value. The text field is directly editable — typing a value and committing it (blur or Enter) updates `value` the same as picking a color from the swatch.
|
|
269
269
|
|
|
270
|
-
|
|
270
|
+
There's no alpha/transparency support — `<input type="color">` has no concept of it, so `value` is always a plain 6-digit `#rrggbb`.
|
|
271
271
|
|
|
272
|
-
|
|
272
|
+
### Hex format and validation
|
|
273
|
+
|
|
274
|
+
`value` must be exactly `#RRGGBB` (6 hex digits after `#`, case-insensitive). When typing in the text field:
|
|
275
|
+
|
|
276
|
+
- Only `#` and hex digits (`0-9a-fA-F`) can be typed, capped at 6 digits — anything else is blocked or truncated as you type.
|
|
277
|
+
- The value is validated on commit (blur or Enter), not on every keystroke, so you can type through incomplete intermediate states.
|
|
278
|
+
- A missing leading `#` is added automatically on commit (e.g. typing `ff0000` commits as `#ff0000`).
|
|
279
|
+
- If the committed text isn't a valid `#RRGGBB` string, the field reverts to the last valid value — `onchange` is not called.
|
|
273
280
|
|
|
274
281
|
### Disabled and readonly states
|
|
275
282
|
|
|
276
|
-
- **Disabled**: The color picker is non-interactive. The visual swatch is dimmed.
|
|
277
|
-
- **Readonly**: The color picker is non-interactive but the
|
|
283
|
+
- **Disabled**: The color picker is non-interactive. The visual swatch is dimmed, and the hex field is disabled.
|
|
284
|
+
- **Readonly**: The color picker is non-interactive but fully visible — the swatch blocks clicks (it can't open the native picker) and the hex field becomes a non-editable (but not dimmed) readonly text field.
|
|
278
285
|
|
|
279
286
|
## Accessibility
|
|
280
287
|
|
|
@@ -40,7 +40,7 @@ import ColorPicker from "@ticatec/uniface-element/ColorPicker";
|
|
|
40
40
|
|
|
41
41
|
| 属性 | 类型 | 默认值 | 说明 |
|
|
42
42
|
|------|------|--------|------|
|
|
43
|
-
| `value` | `string`(可绑定) | `"#000000"` |
|
|
43
|
+
| `value` | `string`(可绑定) | `"#000000"` | `#RRGGBB` 格式的颜色(例如 `#3b82f6`)。`bind:value={...}` 用于双向绑定。 |
|
|
44
44
|
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | 视觉风格变体。 |
|
|
45
45
|
| `compact` | `boolean` | `false` | 紧凑布局,适用于表格单元格和行内表单。 |
|
|
46
46
|
| `disabled` | `boolean` | `false` | 完全禁用 —— 颜色选择器不可交互。 |
|
|
@@ -263,18 +263,25 @@ import ColorPicker from "@ticatec/uniface-element/ColorPicker";
|
|
|
263
263
|
|
|
264
264
|
## 行为说明
|
|
265
265
|
|
|
266
|
-
### 原生颜色输入
|
|
266
|
+
### 原生颜色输入 + 可编辑的 hex 文本框
|
|
267
267
|
|
|
268
|
-
|
|
268
|
+
组件并排展示两部分:原生 `<input type="color">` 色板(点击打开浏览器内置的颜色选择器)和展示 hex 值的文本框。文本框可以直接编辑——输入一个值并提交(失焦或回车)后,`value` 会像通过色板选色一样更新。
|
|
269
269
|
|
|
270
|
-
|
|
270
|
+
不支持透明通道——`<input type="color">` 本身没有这个概念,因此 `value` 始终是纯 6 位 `#rrggbb`。
|
|
271
271
|
|
|
272
|
-
|
|
272
|
+
### Hex 格式与校验
|
|
273
|
+
|
|
274
|
+
`value` 必须是合法的 `#RRGGBB`(`#` 后跟 6 位十六进制数字,大小写不敏感)。在文本框中输入时:
|
|
275
|
+
|
|
276
|
+
- 只能输入 `#` 和十六进制字符(`0-9a-fA-F`),最多 6 位——其他字符在输入时会被拦截或截断。
|
|
277
|
+
- 校验只在提交时(失焦或回车)进行,不是每次按键都校验,因此可以正常输入中间的不完整状态。
|
|
278
|
+
- 提交时如果缺少开头的 `#` 会自动补上(例如输入 `ff0000` 会被提交为 `#ff0000`)。
|
|
279
|
+
- 如果提交的文本不是合法的 `#RRGGBB`,文本框会回退到上一个合法值——不会触发 `onchange`。
|
|
273
280
|
|
|
274
281
|
### 禁用和只读状态
|
|
275
282
|
|
|
276
|
-
-
|
|
277
|
-
-
|
|
283
|
+
- **禁用**:颜色选择器不可交互。视觉色板变暗,hex 文本框也被禁用。
|
|
284
|
+
- **只读**:颜色选择器不可交互,但完全可见——色板会拦截点击(无法打开原生选择器),hex 文本框变为不可编辑(但不变暗)的只读文本框。
|
|
278
285
|
|
|
279
286
|
## 无障碍
|
|
280
287
|
|
|
@@ -53,7 +53,14 @@
|
|
|
53
53
|
</script>
|
|
54
54
|
|
|
55
55
|
<FormEditor {theme} {tooltip} {error} {style} {readonly} {disabled} {compact} {variant}>
|
|
56
|
-
|
|
56
|
+
<!-- Decorative flex wrapper only: the real interactive control is the
|
|
57
|
+
<input>/children snippet rendered inside, which carries its own
|
|
58
|
+
semantics — this div must not steal or hide them via role/aria-hidden.
|
|
59
|
+
onclick here only forwards focus to that inner control, it's not an
|
|
60
|
+
independent action, so no interactive role/keyboard handler applies. -->
|
|
61
|
+
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
62
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
63
|
+
<div class="uniface-common-editor" bind:this={container} {style}
|
|
57
64
|
onmousedown={(e: MouseEvent)=>{e.preventDefault()}} onclick={handleContainerClick}>
|
|
58
65
|
{#if leadingIcon}
|
|
59
66
|
<div class="editor-embed-icon" style="flex: 0 0 auto;">
|
|
@@ -69,9 +76,16 @@
|
|
|
69
76
|
{:else}
|
|
70
77
|
<div class={input$class} style="position: relative; flex: 1 1 auto">
|
|
71
78
|
{@render children()}
|
|
72
|
-
{#if
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
{#if canClean}
|
|
80
|
+
<!-- Reserved unconditionally (not gated on textValue) so
|
|
81
|
+
.uniface-common-editor:has(.clean-icon)'s input
|
|
82
|
+
padding-right in uniface-form-editor.scss stays
|
|
83
|
+
constant — otherwise the editor visibly grows/shifts
|
|
84
|
+
the moment text is first entered. -->
|
|
85
|
+
<div class="clean-icon" class:has-value={textValue}>
|
|
86
|
+
<i class="icon_google_clear" role="button" tabindex={textValue ? 0 : -1} aria-label="Clear"
|
|
87
|
+
onmousedown={(e: MouseEvent)=>{e.preventDefault()}} onclick={textValue ? clear : undefined}
|
|
88
|
+
onkeydown={(e: KeyboardEvent) => { if (textValue && (e.key === 'Enter' || e.key === ' ')) { e.preventDefault(); clear?.(); } }}></i>
|
|
75
89
|
</div>
|
|
76
90
|
{/if}
|
|
77
91
|
</div>
|
|
@@ -70,7 +70,6 @@
|
|
|
70
70
|
let editorElement: HTMLElement | undefined = $state();
|
|
71
71
|
let editor: HTMLDivElement | undefined = $state();
|
|
72
72
|
let hasFocus = $state(false);
|
|
73
|
-
let canClean = $state(!mandatory && value != null);
|
|
74
73
|
|
|
75
74
|
|
|
76
75
|
const handleFocus = (event: FocusEvent) => {
|
|
@@ -111,7 +110,6 @@
|
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
$effect(() => {
|
|
114
|
-
canClean = !mandatory && value != null;
|
|
115
113
|
if (!isOpen && hasFocus) {
|
|
116
114
|
setTimeout(() => {
|
|
117
115
|
if (document.activeElement !== editor) {
|
|
@@ -148,20 +146,28 @@
|
|
|
148
146
|
<input style={input$style} tabindex="-1" readonly {disabled} value={textValue}/>
|
|
149
147
|
{/if}
|
|
150
148
|
{:else}
|
|
151
|
-
<div style="flex: 1 1 auto; position: relative; overflow: hidden; height: 100%"
|
|
149
|
+
<div style="flex: 1 1 auto; position: relative; overflow: hidden; height: 100%">
|
|
152
150
|
{#if input$readonly}
|
|
153
|
-
<input bind:this={editor} style={input$style} value={textValue} readonly {placeholder} onkeydown={handleKeyDown}
|
|
151
|
+
<input bind:this={editor} style={input$style} value={textValue} readonly {placeholder} onclick={openPopup} onkeydown={handleKeyDown}
|
|
154
152
|
tabindex="0"/>
|
|
155
153
|
{:else}
|
|
156
|
-
<input bind:this={editor} style={input$style} value={textValue} {oninput} {oncompositionstart} {oncompositionend}
|
|
154
|
+
<input bind:this={editor} style={input$style} value={textValue} {oninput} {oncompositionstart} {oncompositionend} onclick={openPopup}
|
|
157
155
|
{placeholder} tabindex="0" onkeydown={handleKeyDown}/>
|
|
158
156
|
{/if}
|
|
159
157
|
{#if children}
|
|
160
158
|
{@render children()}
|
|
161
159
|
{/if}
|
|
162
|
-
{#if
|
|
163
|
-
|
|
164
|
-
|
|
160
|
+
{#if !mandatory}
|
|
161
|
+
<!-- Space is reserved (and input padding-right adjusted via
|
|
162
|
+
.uniface-common-picker:has(.clean-icon) in
|
|
163
|
+
uniface-form-editor.scss) whenever clearing is allowed
|
|
164
|
+
at all, not only once a value is picked — otherwise the
|
|
165
|
+
whole picker visibly grows/shifts by that padding the
|
|
166
|
+
moment a value is first selected. Visibility of the
|
|
167
|
+
glyph itself still depends on there being something to
|
|
168
|
+
clear. -->
|
|
169
|
+
<div class="clean-icon" class:has-value={textValue}>
|
|
170
|
+
<i class="icon_google_clear" role="none" onclick={textValue ? doClean : undefined}></i>
|
|
165
171
|
</div>
|
|
166
172
|
{/if}
|
|
167
173
|
</div>
|
|
@@ -181,5 +187,3 @@
|
|
|
181
187
|
{/if}
|
|
182
188
|
</Popover>
|
|
183
189
|
{/if}
|
|
184
|
-
|
|
185
|
-
|
|
@@ -57,6 +57,12 @@
|
|
|
57
57
|
showPopup = false;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
const handleTriggerKeyDown = (e: KeyboardEvent) => {
|
|
61
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
openPopup();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
60
66
|
</script>
|
|
61
67
|
|
|
62
68
|
<CommonEditor
|
|
@@ -76,7 +82,8 @@
|
|
|
76
82
|
|
|
77
83
|
{#snippet trailingIcon()}
|
|
78
84
|
{#if !disabled && !readonly}
|
|
79
|
-
<i class="icon_google_arrow_drop_down" aria-
|
|
85
|
+
<i class="icon_google_arrow_drop_down" role="button" tabindex="0" aria-label="Open" aria-expanded={showPopup}
|
|
86
|
+
onclick={openPopup} onkeydown={handleTriggerKeyDown}></i>
|
|
80
87
|
{/if}
|
|
81
88
|
{/snippet}
|
|
82
89
|
|