@ticatec/uniface-element 5.0.1 → 5.0.3
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/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/data_display/card/CommonCardActionBar.svelte +34 -14
- 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 +90 -15
- 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/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 +9 -9
- package/dist/form/attachment_files/FileRender.svelte +1 -1
- package/dist/form/attachment_files/FileUploadPanel.svelte +5 -1
- package/dist/form/cascade_options_select/CascadeOptionSelect.svelte +10 -2
- package/dist/form/cascade_options_select/OptionsBox.svelte +48 -2
- package/dist/form/color_picker/ColorPickerPanel.svelte +23 -20
- package/dist/form/color_picker/ColorPickerPanel.svelte.d.ts +5 -18
- package/dist/form/common_editor/CommonEditor.svelte +36 -5
- package/dist/form/common_editor/CommonPicker.svelte +11 -4
- package/dist/form/common_editor/CommonPopupEditor.svelte +11 -2
- 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 +8 -2
- 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/number_editor/NumberEditor.svelte +2 -0
- package/dist/form/options_multi_select/OptionsMultiSelect.svelte +19 -3
- 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 +12 -3
- package/dist/form/search_box/SearchBox.svelte +2 -1
- package/dist/form/switch/Switch.svelte +4 -4
- package/dist/form/text_editor/PasswordEditor.svelte +2 -1
- package/dist/form/text_editor/TextEditor.svelte +2 -1
- package/dist/form/time_editor/TimeEditor.svelte +2 -0
- package/dist/form/unit-number-editor/UnitNumberEditor.svelte +13 -2
- package/dist/form/unit-number-editor/UnitNumberEditor.svelte.d.ts +1 -0
- package/dist/general/button/Button.svelte +3 -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/tag/Tag.svelte +9 -1
- package/dist/navigation/nav_menu/NavigatorMenu.svelte +2 -2
- package/dist/navigation/nav_menu/NavigatorMenuItem.svelte +10 -1
- 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/tabs/Tabs.svelte +42 -10
- package/dist/navigation/tabs/Tabs.svelte.d.ts +2 -2
- package/dist/overlay/common/FloatingPanel.svelte +3 -11
- 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 +56 -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/context-menu/ContextMenu.svelte.js +2 -15
- package/dist/overlay/context-menu/ContextMenuPanel.svelte +13 -1
- package/dist/overlay/dialog/Dialog.svelte +46 -29
- package/dist/overlay/dialog/DialogManager.svelte.js +7 -9
- 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 +102 -7
- package/dist/types.d.ts +4 -3
- 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
|
@@ -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}
|
|
@@ -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()}
|
|
@@ -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
|
|
@@ -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
|
-
|
|
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-
|
|
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>
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
{:else}
|
|
115
115
|
<nav bind:this={horizontalMenu} class="uniface-navigator-menu horizontal" {style} data-theme={theme || undefined}>
|
|
116
116
|
{#if hasOverflow}
|
|
117
|
-
<button class="scroll-button previous" aria-label="向左滚动菜单" disabled={!canScrollLeft} onclick={() => scrollMenu(-1)}>
|
|
117
|
+
<button type="button" class="scroll-button previous" aria-label="向左滚动菜单" disabled={!canScrollLeft} onclick={() => scrollMenu(-1)}>
|
|
118
118
|
<i aria-hidden="true"></i>
|
|
119
119
|
</button>
|
|
120
120
|
{/if}
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
</div>
|
|
140
140
|
</div>
|
|
141
141
|
{#if hasOverflow}
|
|
142
|
-
<button class="scroll-button next" aria-label="向右滚动菜单" disabled={!canScrollRight} onclick={() => scrollMenu(1)}>
|
|
142
|
+
<button type="button" class="scroll-button next" aria-label="向右滚动菜单" disabled={!canScrollRight} onclick={() => scrollMenu(1)}>
|
|
143
143
|
<i aria-hidden="true"></i>
|
|
144
144
|
</button>
|
|
145
145
|
{/if}
|
|
@@ -60,12 +60,21 @@
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
function handleMenuItemKeyDown(e: KeyboardEvent) {
|
|
65
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
66
|
+
e.preventDefault();
|
|
67
|
+
handleMenuItemClick();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
63
70
|
</script>
|
|
64
71
|
|
|
65
72
|
<li bind:this={liEl} class:expandable class:fold={!expand} class:cascade class:fly-left={flyLeft}>
|
|
66
73
|
<span
|
|
67
74
|
onclick={handleMenuItemClick}
|
|
68
|
-
|
|
75
|
+
onkeydown={handleMenuItemKeyDown}
|
|
76
|
+
role="button" tabindex="0"
|
|
77
|
+
aria-expanded={expandable ? expand : undefined}
|
|
69
78
|
>
|
|
70
79
|
<span class="label">{menuText}</span>
|
|
71
80
|
{#if expandable}
|
|
@@ -26,16 +26,23 @@
|
|
|
26
26
|
activeItem = item;
|
|
27
27
|
itemClickHandler?.(item);
|
|
28
28
|
};
|
|
29
|
+
|
|
30
|
+
const handleKeyDown = (item: any) => (e: KeyboardEvent) => {
|
|
31
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
handleClick(item);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
29
36
|
</script>
|
|
30
37
|
|
|
31
38
|
<div class="uniface-navigator-panel" {style}>
|
|
32
|
-
<div class="navigator-content">
|
|
39
|
+
<div class="navigator-content" role="list">
|
|
33
40
|
{#each items as item}
|
|
34
41
|
<div class="uniface-navigator-item {retrieveStatus?.(item) ?? NavItemStatus.Completed}"
|
|
35
42
|
class:active={activeItem === item}
|
|
36
43
|
class:highlight={highlights.indexOf(item) > -1}
|
|
37
|
-
aria-
|
|
38
|
-
onclick={() => handleClick(item)}>
|
|
44
|
+
role="button" tabindex="0" aria-current={activeItem === item ? 'step' : undefined}
|
|
45
|
+
onclick={() => handleClick(item)} onkeydown={handleKeyDown(item)}>
|
|
39
46
|
<span>{item.text}</span>
|
|
40
47
|
</div>
|
|
41
48
|
{/each}
|
|
@@ -44,15 +51,7 @@
|
|
|
44
51
|
|
|
45
52
|
<style>
|
|
46
53
|
.uniface-navigator-panel {
|
|
47
|
-
--uniface-navigator-background-color: var(--uniface-application-bg);
|
|
48
|
-
--uniface-navigator-vertical-padding: 16px;
|
|
49
|
-
--uniface-navigator-completed-text-color: #374151;
|
|
50
|
-
--uniface-navigator-not-start-text-color: #6B7280;
|
|
51
|
-
--uniface-navigator-warning-dot-color: #C62828;
|
|
52
|
-
--uniface-navigator-hover-text-color: #298DFF;
|
|
53
|
-
--uniface-navigator-active-text-color: #0061FF;
|
|
54
54
|
--uniface-navigator-active-text-weight: 600;
|
|
55
|
-
--uniface-navigator-highlight-text-color: #0061FF;
|
|
56
55
|
|
|
57
56
|
position: relative;
|
|
58
57
|
width: 100%;
|
|
@@ -76,7 +75,7 @@
|
|
|
76
75
|
font-size: 12px;
|
|
77
76
|
padding: 4px 8px 4px 24px;
|
|
78
77
|
position: relative;
|
|
79
|
-
background: linear-gradient(to right, transparent 12px,
|
|
78
|
+
background: linear-gradient(to right, transparent 12px, var(--uniface-navigator-connector-color) 12px, var(--uniface-navigator-connector-color) 13px, transparent 13px);
|
|
80
79
|
}
|
|
81
80
|
|
|
82
81
|
.uniface-navigator-item:first-child {
|
|
@@ -134,14 +133,15 @@
|
|
|
134
133
|
.uniface-navigator-item.active::before {
|
|
135
134
|
content: "";
|
|
136
135
|
position: absolute;
|
|
137
|
-
left:
|
|
136
|
+
left: 8px;
|
|
138
137
|
top: 50%;
|
|
139
138
|
transform: translateY(-50%);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
box-sizing: border-box;
|
|
140
|
+
width: 10px;
|
|
141
|
+
height: 10px;
|
|
142
|
+
border: 3px solid var(--uniface-navigator-active-text-color);
|
|
143
143
|
border-radius: 50%;
|
|
144
|
-
background-color: white;
|
|
144
|
+
background-color: var(--uniface-navigator-background-color, white);
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
.uniface-navigator-item.active:hover {
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {untrack} from 'svelte';
|
|
3
|
+
import type {Snippet} from 'svelte';
|
|
4
|
+
import type {TransitionConfig} from 'svelte/transition';
|
|
5
|
+
import {fly} from 'svelte/transition';
|
|
6
|
+
import {cubicOut} from 'svelte/easing';
|
|
7
|
+
import PageStackFrame from './PageStackFrame.svelte';
|
|
8
|
+
import {providePageStackContext} from './PageStackContext';
|
|
9
|
+
|
|
10
|
+
interface StackEntry {
|
|
11
|
+
id: string;
|
|
12
|
+
component: any;
|
|
13
|
+
props: Record<string, any>;
|
|
14
|
+
resolve: (value: any) => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type TransitionFn = (node: Element, params?: any) => TransitionConfig;
|
|
18
|
+
|
|
19
|
+
interface Props {
|
|
20
|
+
style?: string;
|
|
21
|
+
/** 每一帧 push/pop 的滑入滑出时长(ms)。仅在没有传 transitionParams 时生效;设为 0 关闭动画。 */
|
|
22
|
+
transitionDuration?: number;
|
|
23
|
+
/**
|
|
24
|
+
* 换成任意 svelte/transition 函数(fly/fade/scale/slide...)或自定义的过渡函数。
|
|
25
|
+
* 默认是从右侧滑入的 fly,效果同 transitionParams 未设置时的 {x:'100%', duration:transitionDuration, easing:cubicOut}。
|
|
26
|
+
*/
|
|
27
|
+
transition?: TransitionFn;
|
|
28
|
+
/** 传给 transition 函数的参数;一旦提供,会完全替代基于 transitionDuration 生成的默认参数。 */
|
|
29
|
+
transitionParams?: Record<string, any>;
|
|
30
|
+
/** 根页面(初始内容,depth = 0) */
|
|
31
|
+
children?: Snippet;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let {
|
|
35
|
+
style = '',
|
|
36
|
+
transitionDuration = 260,
|
|
37
|
+
transition = fly,
|
|
38
|
+
transitionParams,
|
|
39
|
+
children
|
|
40
|
+
}: Props = $props();
|
|
41
|
+
|
|
42
|
+
let resolvedTransitionParams = $derived(
|
|
43
|
+
transitionParams ?? {x: '100%', duration: transitionDuration, easing: cubicOut}
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
let stack = $state<StackEntry[]>([]);
|
|
47
|
+
|
|
48
|
+
const generateId = (): string => `page_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
49
|
+
|
|
50
|
+
function closeEntry(id: string, result?: any): void {
|
|
51
|
+
// untrack: push()/close()/reset() are meant to be callable from anywhere,
|
|
52
|
+
// including from inside a caller's own $effect (e.g. a page that
|
|
53
|
+
// auto-navigates further based on its props). Reading `stack` (to find/
|
|
54
|
+
// filter it) *and* writing it back in the same synchronous call would
|
|
55
|
+
// otherwise get attributed to whatever effect happens to be running at
|
|
56
|
+
// call time, and the write would then re-trigger that same effect —
|
|
57
|
+
// Svelte reports this as "effect reads and writes the same state" /
|
|
58
|
+
// effect_update_depth_exceeded. untrack() keeps this internal
|
|
59
|
+
// read+write from being picked up as a dependency of an unrelated,
|
|
60
|
+
// currently-running effect; existing subscribers of `stack` (the
|
|
61
|
+
// {#each} below) are unaffected — untrack only suppresses *new*
|
|
62
|
+
// spurious subscriptions created during this call.
|
|
63
|
+
let entry: StackEntry | undefined;
|
|
64
|
+
untrack(() => {
|
|
65
|
+
entry = stack.find(e => e.id === id);
|
|
66
|
+
if (!entry) return;
|
|
67
|
+
// 先移除再 resolve:resolve 可能同步触发调用方的后续逻辑(比如再次 push),
|
|
68
|
+
// 那时候这一帧必须已经不在栈里了。
|
|
69
|
+
stack = stack.filter(e => e.id !== id);
|
|
70
|
+
});
|
|
71
|
+
entry?.resolve(result);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* push 一个组件进栈,覆盖显示在当前内容之上。返回的 Promise 在该页面调用
|
|
76
|
+
* getPageStack().close(result) 时以 result resolve;也可以用 PageStack 实例的
|
|
77
|
+
* pop(result) 从外部(比如 bottombar 的返回按钮)关闭当前栈顶。
|
|
78
|
+
*/
|
|
79
|
+
export function push<R = any>(component: any, props: Record<string, any> = {}): Promise<R> {
|
|
80
|
+
return new Promise<R>(resolve => {
|
|
81
|
+
const id = generateId();
|
|
82
|
+
// see closeEntry() above for why this is wrapped in untrack()
|
|
83
|
+
untrack(() => {
|
|
84
|
+
stack = [...stack, {id, component, props, resolve: resolve as (v: any) => void}];
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** 关闭当前栈顶的一帧。栈为空时是 no-op。 */
|
|
90
|
+
export function pop(result?: any): void {
|
|
91
|
+
const top = stack[stack.length - 1];
|
|
92
|
+
if (top) closeEntry(top.id, result);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** 清空整个栈,直接回到根页面。不逐帧过渡,适合"注销/切换上下文"这类场景。 */
|
|
96
|
+
export function reset(): void {
|
|
97
|
+
// see closeEntry() above for why this is wrapped in untrack()
|
|
98
|
+
let entries: StackEntry[] = [];
|
|
99
|
+
untrack(() => {
|
|
100
|
+
entries = stack;
|
|
101
|
+
stack = [];
|
|
102
|
+
});
|
|
103
|
+
entries.forEach(entry => entry.resolve(undefined));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 根页面(children)本身也活在这个 context 里,depth = 0,close() 是 no-op——
|
|
107
|
+
// 根页面不是被 push 进来的,没有"关闭返回上一层"的语义,但它应该能拿到 push()
|
|
108
|
+
// 来发起第一层导航,不需要额外用 bind:this 去引用 PageStack 实例。
|
|
109
|
+
providePageStackContext({
|
|
110
|
+
close: () => {
|
|
111
|
+
if (typeof console !== 'undefined') {
|
|
112
|
+
console.warn('[PageStack] root page has no close() semantics — it was not pushed onto the stack');
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
push,
|
|
116
|
+
depth: 0
|
|
117
|
+
});
|
|
118
|
+
</script>
|
|
119
|
+
|
|
120
|
+
<div class="uniface-page-stack" {style}>
|
|
121
|
+
<div class="page-stack-root" inert={stack.length > 0}>
|
|
122
|
+
{@render children?.()}
|
|
123
|
+
</div>
|
|
124
|
+
{#each stack as entry, i (entry.id)}
|
|
125
|
+
<div class="page-stack-frame" style="z-index: {i + 1}" inert={i < stack.length - 1}
|
|
126
|
+
transition:transition={resolvedTransitionParams}>
|
|
127
|
+
<PageStackFrame
|
|
128
|
+
id={entry.id}
|
|
129
|
+
component={entry.component}
|
|
130
|
+
props={entry.props}
|
|
131
|
+
depth={i + 1}
|
|
132
|
+
close={(result) => closeEntry(entry.id, result)}
|
|
133
|
+
{push}
|
|
134
|
+
/>
|
|
135
|
+
</div>
|
|
136
|
+
{/each}
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<style>
|
|
140
|
+
.uniface-page-stack {
|
|
141
|
+
width: 100%;
|
|
142
|
+
height: 100%;
|
|
143
|
+
position: relative;
|
|
144
|
+
overflow: hidden;
|
|
145
|
+
box-sizing: border-box;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.page-stack-root {
|
|
149
|
+
width: 100%;
|
|
150
|
+
height: 100%;
|
|
151
|
+
position: relative;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.page-stack-frame {
|
|
155
|
+
position: absolute;
|
|
156
|
+
inset: 0;
|
|
157
|
+
overflow: auto;
|
|
158
|
+
background-color: var(--uniface-page-stack-color-surface, var(--uniface-color-surface));
|
|
159
|
+
}
|
|
160
|
+
</style>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { TransitionConfig } from 'svelte/transition';
|
|
3
|
+
type TransitionFn = (node: Element, params?: any) => TransitionConfig;
|
|
4
|
+
interface Props {
|
|
5
|
+
style?: string;
|
|
6
|
+
/** 每一帧 push/pop 的滑入滑出时长(ms)。仅在没有传 transitionParams 时生效;设为 0 关闭动画。 */
|
|
7
|
+
transitionDuration?: number;
|
|
8
|
+
/**
|
|
9
|
+
* 换成任意 svelte/transition 函数(fly/fade/scale/slide...)或自定义的过渡函数。
|
|
10
|
+
* 默认是从右侧滑入的 fly,效果同 transitionParams 未设置时的 {x:'100%', duration:transitionDuration, easing:cubicOut}。
|
|
11
|
+
*/
|
|
12
|
+
transition?: TransitionFn;
|
|
13
|
+
/** 传给 transition 函数的参数;一旦提供,会完全替代基于 transitionDuration 生成的默认参数。 */
|
|
14
|
+
transitionParams?: Record<string, any>;
|
|
15
|
+
/** 根页面(初始内容,depth = 0) */
|
|
16
|
+
children?: Snippet;
|
|
17
|
+
}
|
|
18
|
+
declare const PageStack: import("svelte").Component<Props, {
|
|
19
|
+
push: <R = any>(component: any, props?: Record<string, any>) => Promise<R>;
|
|
20
|
+
pop: (result?: any) => void;
|
|
21
|
+
reset: () => void;
|
|
22
|
+
}, "">;
|
|
23
|
+
type PageStack = ReturnType<typeof PageStack>;
|
|
24
|
+
export default PageStack;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 每一层被 push 进 PageStack 的页面组件,都可以通过 getPageStack() 拿到这个 API。
|
|
3
|
+
* 根页面(PageStack 的 children)同样能拿到(depth = 0),但它的 close() 是 no-op——
|
|
4
|
+
* 根页面不是被 push 进来的,没有"关闭并返回上一层"这个语义。
|
|
5
|
+
*/
|
|
6
|
+
export interface PageStackApi<T = any> {
|
|
7
|
+
/**
|
|
8
|
+
* 关闭当前页面。对应这一页 push() 时返回的 Promise 会以 result resolve。
|
|
9
|
+
* 根页面调用无效果(会在开发模式下打一条 warning)。
|
|
10
|
+
*/
|
|
11
|
+
close: (result?: T) => void;
|
|
12
|
+
/**
|
|
13
|
+
* 在当前页面之上继续 push 一个新页面,和 PageStack 实例上的 push() 是同一个函数——
|
|
14
|
+
* 多级 drill-down 时不需要一路把最外层的 PageStack 引用传下去。
|
|
15
|
+
*/
|
|
16
|
+
push: <R = any>(component: any, props?: Record<string, any>) => Promise<R>;
|
|
17
|
+
/** 当前页面在栈中的深度,根页面为 0,第一层 push 进来的页面为 1,以此类推。 */
|
|
18
|
+
depth: number;
|
|
19
|
+
}
|
|
20
|
+
export declare function providePageStackContext(api: PageStackApi): void;
|
|
21
|
+
/**
|
|
22
|
+
* 在被 PageStack push 进来的页面组件(或它的任意后代)里调用,拿到 {close, push, depth}。
|
|
23
|
+
* 在 PageStack 之外调用返回 undefined。
|
|
24
|
+
*/
|
|
25
|
+
export declare function getPageStack<T = any>(): PageStackApi<T> | undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { getContext, setContext, hasContext } from 'svelte';
|
|
2
|
+
const CONTEXT_KEY = 'uniface-page-stack';
|
|
3
|
+
export function providePageStackContext(api) {
|
|
4
|
+
setContext(CONTEXT_KEY, api);
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* 在被 PageStack push 进来的页面组件(或它的任意后代)里调用,拿到 {close, push, depth}。
|
|
8
|
+
* 在 PageStack 之外调用返回 undefined。
|
|
9
|
+
*/
|
|
10
|
+
export function getPageStack() {
|
|
11
|
+
return hasContext(CONTEXT_KEY) ? getContext(CONTEXT_KEY) : undefined;
|
|
12
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {providePageStackContext} from './PageStackContext';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
id: string;
|
|
6
|
+
component: any;
|
|
7
|
+
props: Record<string, any>;
|
|
8
|
+
depth: number;
|
|
9
|
+
close: (result?: any) => void;
|
|
10
|
+
push: <R = any>(component: any, props?: Record<string, any>) => Promise<R>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let {id, component: Comp, props, depth, close, push}: Props = $props();
|
|
14
|
+
|
|
15
|
+
// Context identity is fixed for the lifetime of this frame — mirrors
|
|
16
|
+
// DialogWrapper's getInitialDialogId pattern (overlay/dialog/DialogWrapper.svelte):
|
|
17
|
+
// later prop changes (e.g. depth staying the same but close/push identity
|
|
18
|
+
// churning on parent re-render) must not replace what this frame's
|
|
19
|
+
// descendants already captured via getPageStack().
|
|
20
|
+
const getInitialContext = () => ({close, push, depth});
|
|
21
|
+
providePageStackContext(getInitialContext());
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<Comp {...props}/>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
id: string;
|
|
3
|
+
component: any;
|
|
4
|
+
props: Record<string, any>;
|
|
5
|
+
depth: number;
|
|
6
|
+
close: (result?: any) => void;
|
|
7
|
+
push: <R = any>(component: any, props?: Record<string, any>) => Promise<R>;
|
|
8
|
+
}
|
|
9
|
+
declare const PageStackFrame: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type PageStackFrame = ReturnType<typeof PageStackFrame>;
|
|
11
|
+
export default PageStackFrame;
|