@kubex/zinc 1.1.184 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.browserslistrc +2 -0
- package/.github/workflows/js_build_and_deploy.yaml +54 -1
- package/.github/workflows/test.yaml +27 -0
- package/dist/chunks/zn.UWJLIXDT.js +1 -0
- package/dist/custom-elements.json +10344 -2583
- package/dist/vscode.html-custom-data.json +1102 -125
- package/dist/web-types.json +2217 -224
- package/dist/zn.d.ts +2306 -417
- package/dist/zn.min.css +1 -1
- package/dist/zn.min.js +2313 -1635
- package/docs/_includes/default.njk +4 -1
- package/docs/assets/scripts/docs.js +22 -6
- package/docs/assets/styles/docs.css +9 -2
- package/docs/data/report-table-day-compare.json +380 -0
- package/docs/data/report-table.json +314 -0
- package/docs/pages/components/avatar-group.md +57 -0
- package/docs/pages/components/badge.md +67 -0
- package/docs/pages/components/button.md +41 -1
- package/docs/pages/components/chat-message.md +16 -0
- package/docs/pages/components/checkbox.md +1 -1
- package/docs/pages/components/chip.md +25 -13
- package/docs/pages/components/color-picker.md +37 -0
- package/docs/pages/components/copy-button.md +2 -2
- package/docs/pages/components/data-table-filter.md +33 -50
- package/docs/pages/components/data-table-search.md +4 -4
- package/docs/pages/components/data-table.md +27 -3
- package/docs/pages/components/date-range.md +116 -0
- package/docs/pages/components/dialog.md +29 -37
- package/docs/pages/components/diff-row.md +28 -0
- package/docs/pages/components/diff.md +46 -0
- package/docs/pages/components/editor.md +55 -0
- package/docs/pages/components/filter-wrapper.md +20 -0
- package/docs/pages/components/icon.md +46 -1
- package/docs/pages/components/input.md +30 -11
- package/docs/pages/components/item.md +35 -0
- package/docs/pages/components/key-value.md +25 -0
- package/docs/pages/components/menu.md +74 -7
- package/docs/pages/components/nav-item.md +15 -0
- package/docs/pages/components/nav-list.md +132 -0
- package/docs/pages/components/navbar.md +100 -1
- package/docs/pages/components/page.md +242 -74
- package/docs/pages/components/priority-list.md +43 -5
- package/docs/pages/components/query-builder.md +23 -0
- package/docs/pages/components/radio-group.md +33 -1
- package/docs/pages/components/radio.md +1 -1
- package/docs/pages/components/report-table.md +202 -0
- package/docs/pages/components/stat.md +30 -0
- package/docs/pages/components/tile.md +11 -0
- package/docs/pages/components/tooltip.md +1 -1
- package/docs/pages/components/translation-grid.md +86 -0
- package/docs/pages/components/vertical-stepper.md +108 -64
- package/package.json +2 -1
- package/scss/_global-spacing.scss +2 -2
- package/scss/_root.scss +11 -171
- package/scss/boot.scss +14 -0
- package/scss/mixins/_helper-mixins.scss +24 -2
- package/scss/mixins/_motion-mixins.scss +126 -0
- package/scss/mixins/_spacing-mixins.scss +4 -3
- package/scss/mixins/_tab-indicator-mixins.scss +12 -0
- package/scss/mixins/_typography-mixins.scss +1 -1
- package/scss/mixins/index.scss +14 -0
- package/scss/shared/_base.scss +32 -1
- package/scss/shared/_button-mixin.scss +7 -5
- package/scss/shared/_table.scss +35 -4
- package/scss/shared/nav.scss +4 -0
- package/scss/shared/shimmer.scss +1 -1
- package/scss/table-controls.scss +206 -0
- package/scss/themes/_dark.scss +1 -3
- package/scss/themes/_index.scss +1 -1
- package/scss/themes/_light.scss +46 -6
- package/scss/themes/_modes.scss +11 -11
- package/scss/themes/_openbyte.scss +944 -0
- package/scss/themes/_typography.scss +4 -2
- package/scss/variables/index.scss +0 -9
- package/src/components/alert/alert.component.ts +14 -4
- package/src/components/alert/alert.scss +55 -69
- package/src/components/alert/alert.test.ts +8 -0
- package/src/components/animated-button/animated-button.component.ts +3 -2
- package/src/components/animated-button/animated-button.scss +6 -23
- package/src/components/animated-button/animated-button.test.ts +4 -3
- package/src/components/avatar-group/avatar-group.component.ts +84 -0
- package/src/components/avatar-group/avatar-group.scss +54 -0
- package/src/components/avatar-group/avatar-group.test.ts +59 -0
- package/src/components/avatar-group/index.ts +12 -0
- package/src/components/badge/badge.component.ts +49 -0
- package/src/components/badge/badge.scss +80 -0
- package/src/components/badge/badge.test.ts +34 -0
- package/src/components/badge/index.ts +12 -0
- package/src/components/bulk-actions/bulk-actions.component.ts +14 -2
- package/src/components/button/button.component.ts +242 -11
- package/src/components/button/button.scss +133 -25
- package/src/components/button/button.test.ts +122 -0
- package/src/components/button-menu/button-menu.component.ts +32 -11
- package/src/components/button-menu/button-menu.scss +5 -1
- package/src/components/channel-tile/channel-tile.component.ts +34 -27
- package/src/components/channel-tile/channel-tile.scss +76 -43
- package/src/components/chart/builders.test.ts +46 -0
- package/src/components/chart/builders.ts +27 -3
- package/src/components/chart/chart-live.test.ts +4 -6
- package/src/components/chart/chart.component.ts +125 -5
- package/src/components/chart/chart.scss +121 -0
- package/src/components/chart/chart.test.ts +81 -0
- package/src/components/chat-message/chat-message.component.ts +21 -1
- package/src/components/chat-message/chat-message.scss +13 -2
- package/src/components/chat-message/chat-message.test.ts +9 -0
- package/src/components/checkbox/checkbox.component.ts +61 -27
- package/src/components/checkbox/checkbox.scss +58 -25
- package/src/components/checkbox-group/checkbox-group.component.ts +7 -1
- package/src/components/chip/chip.component.ts +11 -1
- package/src/components/chip/chip.scss +91 -26
- package/src/components/chip/chip.test.ts +17 -0
- package/src/components/collapsible/collapsible.component.ts +17 -3
- package/src/components/collapsible/collapsible.scss +19 -10
- package/src/components/color-picker/color-picker.component.ts +277 -0
- package/src/components/color-picker/color-picker.scss +141 -0
- package/src/components/color-picker/color-picker.test.ts +57 -0
- package/src/components/color-picker/index.ts +12 -0
- package/src/components/cols/cols.component.ts +17 -3
- package/src/components/cols/cols.scss +24 -13
- package/src/components/cols/cols.test.ts +33 -0
- package/src/components/confirm/confirm.component.ts +20 -6
- package/src/components/confirm/confirm.test.ts +52 -0
- package/src/components/content-block/content-block.component.ts +38 -9
- package/src/components/content-block/content-block.scss +11 -5
- package/src/components/content-block/content-block.test.ts +26 -0
- package/src/components/copy-button/copy-button.component.ts +2 -2
- package/src/components/copy-button/copy-button.scss +17 -4
- package/src/components/data-select/data-select.component.ts +3 -1
- package/src/components/data-table/data-table.component.ts +364 -142
- package/src/components/data-table/data-table.scss +133 -60
- package/src/components/data-table/data-table.test.ts +356 -4
- package/src/components/data-table-filter/data-table-filter.component.ts +426 -406
- package/src/components/data-table-filter/data-table-filter.scss +176 -148
- package/src/components/data-table-filter/data-table-filter.test.ts +271 -273
- package/src/components/data-table-search/data-table-search.component.ts +4 -2
- package/src/components/data-table-search/data-table-search.scss +8 -1
- package/src/components/data-table-search/data-table-search.test.ts +29 -0
- package/src/components/date-range/date-range-math.test.ts +78 -0
- package/src/components/date-range/date-range-math.ts +105 -0
- package/src/components/date-range/date-range.component.ts +375 -0
- package/src/components/date-range/date-range.scss +272 -0
- package/src/components/date-range/date-range.test.ts +247 -0
- package/src/components/date-range/index.ts +12 -0
- package/src/components/datepicker/datepicker.component.ts +44 -7
- package/src/components/datepicker/datepicker.scss +9 -0
- package/src/components/datepicker/datepicker.test.ts +2 -2
- package/src/components/dialog/dialog.component.ts +38 -19
- package/src/components/dialog/dialog.scss +65 -36
- package/src/components/dialog/dialog.test.ts +14 -0
- package/src/components/diff/diff.component.ts +55 -0
- package/src/components/diff/diff.scss +46 -0
- package/src/components/diff/diff.test.ts +15 -0
- package/src/components/diff/index.ts +12 -0
- package/src/components/diff-row/diff-row.component.ts +75 -0
- package/src/components/diff-row/diff-row.scss +70 -0
- package/src/components/diff-row/diff-row.test.ts +37 -0
- package/src/components/diff-row/index.ts +12 -0
- package/src/components/dropdown/dropdown.component.ts +12 -10
- package/src/components/dropdown/dropdown.scss +2 -0
- package/src/components/editor/editor.component.ts +159 -11
- package/src/components/editor/editor.scss +250 -1
- package/src/components/editor/editor.test.ts +31 -3
- package/src/components/editor/modules/ai/panel/ai-panel.scss +0 -1
- package/src/components/editor/modules/attachment/attachment.ts +53 -31
- package/src/components/editor/modules/context-menu/context-menu.ts +17 -0
- package/src/components/editor/modules/dialog/dialog.component.ts +23 -1
- package/src/components/editor/modules/dialog/dialog.test.ts +28 -0
- package/src/components/editor/modules/emoji/emoji.ts +4 -5
- package/src/components/editor/modules/merge-field/merge-field.ts +83 -0
- package/src/components/editor/modules/toolbar/toolbar.component.ts +121 -68
- package/src/components/editor/modules/toolbar/toolbar.scss +38 -0
- package/src/components/editor/modules/toolbar/toolbar.ts +25 -1
- package/src/components/empty-state/empty-state.component.ts +6 -1
- package/src/components/empty-state/empty-state.scss +21 -4
- package/src/components/expanding-action/expanding-action.component.ts +22 -34
- package/src/components/expanding-action/expanding-action.scss +3 -45
- package/src/components/expanding-action/expanding-action.test.ts +2 -1
- package/src/components/file/file.component.ts +30 -2
- package/src/components/file/file.scss +6 -0
- package/src/components/filter-wrapper/filter-wrapper.component.ts +45 -10
- package/src/components/filter-wrapper/filter-wrapper.test.ts +58 -2
- package/src/components/flow-builder/flow-builder.component.ts +36 -3
- package/src/components/flow-builder/flow-builder.scss +0 -6
- package/src/components/flow-builder/modules/flow-canvas/flow-canvas.component.ts +8 -0
- package/src/components/flow-builder/modules/flow-canvas/flow-canvas.scss +10 -5
- package/src/components/flow-builder/modules/flow-node/flow-node.component.ts +17 -0
- package/src/components/flow-builder/modules/flow-node/flow-node.scss +10 -0
- package/src/components/form-actions/form-actions.component.ts +48 -2
- package/src/components/form-actions/form-actions.scss +1 -1
- package/src/components/form-group/form-group.component.ts +10 -3
- package/src/components/form-group/form-group.scss +37 -4
- package/src/components/form-group/form-group.test.ts +10 -0
- package/src/components/header/header.component.ts +11 -4
- package/src/components/header/header.scss +47 -5
- package/src/components/hover-container/hover-container.component.ts +4 -5
- package/src/components/icon/icon.component.ts +95 -9
- package/src/components/icon/icon.scss +70 -6
- package/src/components/icon/icon.test.ts +55 -0
- package/src/components/icon-picker/icon-picker.component.ts +35 -1
- package/src/components/inline-edit/inline-edit.component.ts +38 -8
- package/src/components/inline-edit/inline-edit.scss +128 -19
- package/src/components/input/input.component.ts +173 -297
- package/src/components/input/input.scss +65 -43
- package/src/components/input/input.test.ts +86 -4
- package/src/components/item/item.component.ts +12 -0
- package/src/components/item/item.scss +102 -3
- package/src/components/item/item.test.ts +23 -0
- package/src/components/key/key.component.ts +2 -2
- package/src/components/key/key.scss +11 -0
- package/src/components/key-value/index.ts +12 -0
- package/src/components/key-value/key-value.component.ts +160 -0
- package/src/components/key-value/key-value.scss +20 -0
- package/src/components/key-value/key-value.test.ts +22 -0
- package/src/components/markdown-editor/markdown-editor.component.ts +8 -1
- package/src/components/menu/menu.component.ts +21 -2
- package/src/components/menu/menu.scss +43 -23
- package/src/components/menu/menu.test.ts +33 -0
- package/src/components/menu-item/menu-item.component.ts +13 -2
- package/src/components/menu-item/menu-item.scss +56 -23
- package/src/components/menu-item/menu-item.test.ts +31 -0
- package/src/components/menu-item/submenu-controller.ts +25 -15
- package/src/components/menu-label/index.ts +12 -0
- package/src/components/menu-label/menu-label.component.ts +30 -0
- package/src/components/menu-label/menu-label.scss +18 -0
- package/src/components/nav-item/index.ts +12 -0
- package/src/components/nav-item/nav-item.component.ts +83 -0
- package/src/components/nav-item/nav-item.scss +128 -0
- package/src/components/nav-list/index.ts +12 -0
- package/src/components/nav-list/nav-list.component.ts +313 -0
- package/src/components/nav-list/nav-list.scss +87 -0
- package/src/components/nav-list/nav-list.test.ts +250 -0
- package/src/components/navbar/navbar.component.ts +235 -171
- package/src/components/navbar/navbar.scss +333 -169
- package/src/components/navbar/navbar.test.ts +63 -143
- package/src/components/page/page.component.ts +114 -29
- package/src/components/page/page.scss +223 -95
- package/src/components/page/page.test.ts +214 -3
- package/src/components/page-builder/page-builder.component.ts +51 -5
- package/src/components/page-builder/page-builder.scss +6 -1
- package/src/components/page-nav/page-nav.component.ts +25 -3
- package/src/components/page-nav/page-nav.scss +10 -2
- package/src/components/pagination/pagination.scss +1 -1
- package/src/components/panel/panel.component.ts +14 -13
- package/src/components/panel/panel.scss +14 -10
- package/src/components/panel/panel.test.ts +42 -0
- package/src/components/popup/popup.component.ts +20 -13
- package/src/components/popup/popup.test.ts +21 -1
- package/src/components/priority-list/priority-list.component.ts +157 -172
- package/src/components/priority-list/priority-list.scss +113 -17
- package/src/components/priority-list/priority-list.test.ts +301 -3
- package/src/components/progress-bar/progress-bar.component.ts +1 -1
- package/src/components/progress-bar/progress-bar.scss +16 -4
- package/src/components/progress-tile/progress-tile.scss +1 -1
- package/src/components/query-builder/query-builder.component.ts +85 -10
- package/src/components/query-builder/query-builder.scss +7 -1
- package/src/components/query-builder/query-builder.test.ts +40 -0
- package/src/components/radio/radio.component.ts +57 -18
- package/src/components/radio/radio.scss +101 -26
- package/src/components/radio-group/radio-group.component.ts +45 -7
- package/src/components/radio-group/radio-group.scss +17 -0
- package/src/components/radio-group/radio-group.test.ts +63 -2
- package/src/components/rating/rating.component.ts +23 -0
- package/src/components/rating/rating.scss +1 -1
- package/src/components/remarkd-editor/remarkd-editor.component.ts +60 -5
- package/src/components/remarkd-editor/remarkd-editor.scss +12 -4
- package/src/components/report-table/index.ts +12 -0
- package/src/components/report-table/report-format.test.ts +86 -0
- package/src/components/report-table/report-format.ts +72 -0
- package/src/components/report-table/report-math.test.ts +74 -0
- package/src/components/report-table/report-math.ts +252 -0
- package/src/components/report-table/report-table.component.ts +681 -0
- package/src/components/report-table/report-table.scss +328 -0
- package/src/components/report-table/report-table.test.ts +702 -0
- package/src/components/reveal/reveal.component.ts +15 -1
- package/src/components/reveal/reveal.scss +5 -0
- package/src/components/schedule-builder/schedule-builder.component.ts +23 -8
- package/src/components/scroll-container/scroll-container.component.ts +19 -1
- package/src/components/scroll-container/scroll-container.scss +6 -1
- package/src/components/select/select.component.ts +52 -36
- package/src/components/select/select.scss +42 -25
- package/src/components/select/select.test.ts +14 -2
- package/src/components/settings-container/settings-container.scss +18 -5
- package/src/components/sidebar/sidebar.component.ts +8 -1
- package/src/components/sidebar/sidebar.scss +6 -1
- package/src/components/skeleton/skeleton.component.ts +3 -3
- package/src/components/skeleton/skeleton.scss +6 -6
- package/src/components/skeleton/skeleton.test.ts +9 -0
- package/src/components/slash-menu/slash-menu.scss +1 -1
- package/src/components/slideout/slideout.component.ts +20 -3
- package/src/components/slideout/slideout.scss +13 -6
- package/src/components/slideout/slideout.test.ts +19 -0
- package/src/components/split-button/split-button.component.ts +1 -1
- package/src/components/split-pane/split-pane.component.ts +71 -8
- package/src/components/split-pane/split-pane.scss +145 -41
- package/src/components/split-pane/split-pane.test.ts +23 -3
- package/src/components/stat/stat.component.ts +209 -14
- package/src/components/stat/stat.scss +305 -5
- package/src/components/stat/stat.test.ts +143 -2
- package/src/components/status-indicator/status-indicator.scss +22 -21
- package/src/components/stepper/stepper.scss +3 -3
- package/src/components/tab/tab.component.ts +1 -0
- package/src/components/table/table.component.ts +12 -1
- package/src/components/table/table.scss +21 -13
- package/src/components/table/table.test.ts +17 -0
- package/src/components/tabs/tabs.component.ts +150 -37
- package/src/components/tabs/tabs.scss +48 -7
- package/src/components/tabs/tabs.test.ts +169 -0
- package/src/components/textarea/textarea.component.ts +25 -3
- package/src/components/textarea/textarea.scss +10 -0
- package/src/components/textarea/textarea.test.ts +8 -4
- package/src/components/theme-editor/theme-editor.scss +0 -6
- package/src/components/tile/tile.component.ts +32 -2
- package/src/components/tile/tile.scss +40 -7
- package/src/components/tile/tile.test.ts +10 -0
- package/src/components/toggle/toggle.component.ts +23 -7
- package/src/components/toggle/toggle.scss +36 -29
- package/src/components/toggle/toggle.test.ts +17 -0
- package/src/components/tooltip/tooltip.component.ts +3 -0
- package/src/components/tooltip/tooltip.scss +11 -6
- package/src/components/tooltip/tooltip.test.ts +12 -0
- package/src/components/translation-field/index.ts +12 -0
- package/src/components/translation-field/translation-field.component.ts +55 -0
- package/src/components/translation-field/translation-field.scss +101 -0
- package/src/components/translation-fields/index.ts +12 -0
- package/src/components/translation-fields/translation-fields.component.ts +80 -0
- package/src/components/translation-fields/translation-fields.scss +60 -0
- package/src/components/translation-grid/index.ts +12 -0
- package/src/components/translation-grid/translation-grid.component.ts +157 -0
- package/src/components/translation-grid/translation-grid.scss +138 -0
- package/src/components/translation-grid/translation-grid.test.ts +28 -0
- package/src/components/vertical-stepper/vertical-stepper.component.ts +35 -9
- package/src/components/vertical-stepper/vertical-stepper.scss +110 -39
- package/src/components/vertical-stepper/vertical-stepper.test.ts +35 -0
- package/src/components/well/well.scss +2 -2
- package/src/events/events.ts +2 -0
- package/src/events/zn-chart-click.ts +13 -0
- package/src/events/zn-report-change.ts +7 -0
- package/src/form-control.scss +36 -3
- package/src/internal/anchored-popover.ts +175 -0
- package/src/internal/animate.ts +19 -5
- package/src/internal/cosmic-border.ts +15 -0
- package/src/internal/form.ts +1 -1
- package/src/internal/hover-intent.ts +15 -0
- package/src/internal/input-modality.ts +15 -0
- package/src/internal/pointer-intent.ts +37 -0
- package/src/internal/reorder.ts +625 -0
- package/src/internal/scroll.ts +51 -3
- package/src/internal/selection-card.ts +1 -1
- package/src/internal/tab-indicator.ts +92 -0
- package/src/internal/table-sort.ts +25 -0
- package/src/internal/table-tabs.ts +108 -0
- package/src/internal/test-drag.ts +35 -0
- package/src/internal/theme-openbyte.test.ts +126 -0
- package/src/internal/theme.ts +4 -4
- package/src/internal/zinc-element.ts +2 -2
- package/src/selection-card.scss +25 -0
- package/src/types/web-test-runner-commands.d.ts +1 -0
- package/src/utilities/color.test.ts +43 -0
- package/src/utilities/color.ts +189 -0
- package/src/zinc.ts +14 -0
- package/.github/workflows/eleventy_build.yml +0 -42
- package/scss/themes/_aura.scss +0 -114
|
@@ -278,6 +278,9 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
|
|
|
278
278
|
*/
|
|
279
279
|
@property({attribute: 'upload-url'}) uploadUrl = '';
|
|
280
280
|
|
|
281
|
+
/** The largest each file can be, in megabytes. A bigger file makes the control invalid. 0 for no limit. */
|
|
282
|
+
@property({attribute: 'max-size', type: Number}) maxSize = 0;
|
|
283
|
+
|
|
281
284
|
@state() private uploading = false;
|
|
282
285
|
|
|
283
286
|
/** Gets the validity state object */
|
|
@@ -407,13 +410,32 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
|
|
|
407
410
|
this.input.click();
|
|
408
411
|
}
|
|
409
412
|
|
|
413
|
+
private handleDropareaKeyDown(e: KeyboardEvent) {
|
|
414
|
+
if ((e.key === 'Enter' || e.key === ' ') && e.target === e.currentTarget) {
|
|
415
|
+
this.handleClick(e);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
410
419
|
/** Handles the change event of the native input */
|
|
420
|
+
private checkSize(): boolean {
|
|
421
|
+
const tooBig = this.maxSize > 0
|
|
422
|
+
? Array.from(this.files || []).find(file => file.size > this.maxSize * 1024 * 1024)
|
|
423
|
+
: undefined;
|
|
424
|
+
this.setCustomValidity(tooBig ? `${tooBig.name} is larger than the ${this.maxSize} MB limit.` : '');
|
|
425
|
+
return !tooBig;
|
|
426
|
+
}
|
|
427
|
+
|
|
411
428
|
private handleChange(e: Event) {
|
|
412
429
|
e.preventDefault();
|
|
413
430
|
e.stopPropagation();
|
|
414
431
|
|
|
415
432
|
this.updatePreview();
|
|
416
433
|
|
|
434
|
+
if (!this.checkSize()) {
|
|
435
|
+
this.reportValidity();
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
|
|
417
439
|
const file = this.files?.[0];
|
|
418
440
|
if (this.uploadUrl && file) {
|
|
419
441
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
@@ -661,7 +683,11 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
|
|
|
661
683
|
class="input__delete"
|
|
662
684
|
src="close"
|
|
663
685
|
size="16"
|
|
686
|
+
role="button"
|
|
687
|
+
tabindex="0"
|
|
688
|
+
aria-label="${this.localize.term('clearEntry')}"
|
|
664
689
|
@click="${this.removeFile}"
|
|
690
|
+
@keydown="${(e: KeyboardEvent) => (e.key === 'Enter' || e.key === ' ') && this.removeFile(e)}"
|
|
665
691
|
part="delete"></zn-icon>` : ''}
|
|
666
692
|
</zn-chip>
|
|
667
693
|
`)}
|
|
@@ -691,7 +717,7 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
|
|
|
691
717
|
'droparea--has-preview': showImagePreview,
|
|
692
718
|
})}
|
|
693
719
|
@click="${this.handleClick}"
|
|
694
|
-
@
|
|
720
|
+
@keydown="${this.handleDropareaKeyDown}"
|
|
695
721
|
@focus="${this.handleFocus}"
|
|
696
722
|
@blur="${this.handleBlur}"
|
|
697
723
|
tabindex="${this.disabled ? '-1' : '0'}"
|
|
@@ -721,8 +747,10 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
|
|
|
721
747
|
: (hasValue
|
|
722
748
|
? html`<span class="droparea__filename" part="filename">${displayName}</span>`
|
|
723
749
|
: html`
|
|
750
|
+
<!-- The focusable droparea is the control; the button is its label -->
|
|
724
751
|
<zn-button
|
|
725
752
|
class="droparea__upload"
|
|
753
|
+
inert
|
|
726
754
|
icon="cloud_upload"
|
|
727
755
|
icon-size="20"
|
|
728
756
|
panel-bg
|
|
@@ -792,7 +820,7 @@ export default class ZnFile extends ZincElement implements ZincFormControl {
|
|
|
792
820
|
part="form-control">
|
|
793
821
|
${hasTrigger ?
|
|
794
822
|
html`
|
|
795
|
-
<slot name="trigger" part="trigger" @click="${this.handleClick}"
|
|
823
|
+
<slot name="trigger" part="trigger" @click="${this.handleClick}"></slot>` :
|
|
796
824
|
html`
|
|
797
825
|
<label
|
|
798
826
|
aria-hidden="${hasLabel ? 'false' : 'true'}"
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {type CSSResultGroup, html, unsafeCSS} from 'lit';
|
|
2
|
-
import {property} from "lit/decorators.js";
|
|
2
|
+
import {property, state} from "lit/decorators.js";
|
|
3
3
|
import {trimControlValue} from '../../internal/form';
|
|
4
4
|
import ZincElement from '../../internal/zinc-element';
|
|
5
5
|
|
|
6
6
|
import type ZnDataSelect from "../data-select";
|
|
7
|
+
import type ZnButton from "../button";
|
|
7
8
|
import type ZnDataTable from "../data-table";
|
|
8
9
|
import type ZnInput from "../input";
|
|
9
10
|
import type ZnQueryBuilder from "../query-builder";
|
|
@@ -42,12 +43,20 @@ export default class ZnFilterWrapper extends ZincElement {
|
|
|
42
43
|
|
|
43
44
|
@property() button: string = 'Filter';
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
/** Submits the filters when Enter is pressed in a text field. */
|
|
47
|
+
@property({attribute: 'submit-on-enter', type: Boolean}) submitOnEnter = false;
|
|
48
|
+
|
|
49
|
+
/** Shown on the submit button while results load. */
|
|
50
|
+
@property({attribute: 'loading-text'}) loadingText = 'Searching...';
|
|
51
|
+
|
|
52
|
+
@state() private loading = false;
|
|
53
|
+
|
|
54
|
+
private submitButton: ZnButton | null = null;
|
|
46
55
|
|
|
47
56
|
handleSubmit = (event: Event) => {
|
|
48
57
|
event.preventDefault();
|
|
49
58
|
const dataTable: ZnDataTable | null = this.closest('zn-data-table');
|
|
50
|
-
if (dataTable) {
|
|
59
|
+
if (dataTable && !this.loading) {
|
|
51
60
|
const allowedInputs = ['zn-input', 'zn-select', 'zn-query-builder', 'zn-data-select', 'zn-datepicker', 'input', 'select', 'textarea'];
|
|
52
61
|
const inputs = Array.from(this.querySelectorAll(allowedInputs.join(','))) as AllowedInputElement[];
|
|
53
62
|
const params: Record<string, any> = {};
|
|
@@ -60,17 +69,41 @@ export default class ZnFilterWrapper extends ZincElement {
|
|
|
60
69
|
});
|
|
61
70
|
|
|
62
71
|
dataTable.requestParams = params;
|
|
63
|
-
|
|
72
|
+
this.setLoading(true);
|
|
73
|
+
Promise.resolve(dataTable.refresh()).finally(() => this.setLoading(false));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private setLoading(loading: boolean) {
|
|
78
|
+
this.loading = loading;
|
|
79
|
+
if (this.submitButton) {
|
|
80
|
+
this.submitButton.processingText = this.loadingText;
|
|
81
|
+
this.submitButton.processing = loading;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
handleKeyDown = (event: KeyboardEvent) => {
|
|
86
|
+
if (!this.submitOnEnter || event.key !== 'Enter' || event.defaultPrevented || event.isComposing
|
|
87
|
+
|| event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Only plain text fields: selects, buttons and textareas use Enter themselves
|
|
92
|
+
if (event.composedPath()[0] instanceof HTMLInputElement) {
|
|
93
|
+
this.handleSubmit(event);
|
|
64
94
|
}
|
|
65
95
|
}
|
|
66
96
|
|
|
67
97
|
connectedCallback() {
|
|
68
98
|
super.connectedCallback();
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
99
|
+
this.addEventListener('keydown', this.handleKeyDown);
|
|
100
|
+
this.submitButton = this.querySelector('zn-button[submit]');
|
|
101
|
+
this.submitButton?.addEventListener('click', this.handleSubmit);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
disconnectedCallback() {
|
|
105
|
+
super.disconnectedCallback();
|
|
106
|
+
this.removeEventListener('keydown', this.handleKeyDown);
|
|
74
107
|
}
|
|
75
108
|
|
|
76
109
|
private renderDefaultButton() {
|
|
@@ -78,6 +111,8 @@ export default class ZnFilterWrapper extends ZincElement {
|
|
|
78
111
|
<zn-button part="search-button"
|
|
79
112
|
class="filter-wrapper__submit"
|
|
80
113
|
type="submit"
|
|
114
|
+
?processing="${this.loading}"
|
|
115
|
+
processing-text="${this.loadingText}"
|
|
81
116
|
@click="${this.handleSubmit}">
|
|
82
117
|
${this.button}
|
|
83
118
|
</zn-button>
|
|
@@ -87,7 +122,7 @@ export default class ZnFilterWrapper extends ZincElement {
|
|
|
87
122
|
render() {
|
|
88
123
|
return html`
|
|
89
124
|
<slot></slot>
|
|
90
|
-
${this.
|
|
125
|
+
${this.submitButton ? '' : this.renderDefaultButton()}
|
|
91
126
|
`;
|
|
92
127
|
}
|
|
93
128
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import '../../../dist/zn.min.js';
|
|
2
2
|
import { expect, fixture, html } from '@open-wc/testing';
|
|
3
3
|
import { sendKeys } from '@web/test-runner-commands';
|
|
4
|
+
import type ZnButton from '../button';
|
|
4
5
|
import type ZnDataTable from '../data-table';
|
|
5
6
|
import type ZnFilterWrapper from './filter-wrapper.component';
|
|
6
7
|
import type ZnInput from '../input';
|
|
@@ -20,7 +21,7 @@ describe('<zn-filter-wrapper>', () => {
|
|
|
20
21
|
</zn-filter-wrapper>
|
|
21
22
|
</zn-data-table>
|
|
22
23
|
`);
|
|
23
|
-
table.refresh = () => undefined;
|
|
24
|
+
table.refresh = async () => undefined;
|
|
24
25
|
const wrapper = table.querySelector<ZnFilterWrapper>('zn-filter-wrapper')!;
|
|
25
26
|
const input = table.querySelector<ZnInput>('zn-input')!;
|
|
26
27
|
await input.updateComplete;
|
|
@@ -40,7 +41,7 @@ describe('<zn-filter-wrapper>', () => {
|
|
|
40
41
|
</zn-filter-wrapper>
|
|
41
42
|
</zn-data-table>
|
|
42
43
|
`);
|
|
43
|
-
table.refresh = () => undefined;
|
|
44
|
+
table.refresh = async () => undefined;
|
|
44
45
|
const [input, clean] = table.querySelectorAll<ZnInput>('zn-input');
|
|
45
46
|
await input.updateComplete;
|
|
46
47
|
|
|
@@ -53,4 +54,59 @@ describe('<zn-filter-wrapper>', () => {
|
|
|
53
54
|
expect(table.requestParams.email).to.equal('a@b.com');
|
|
54
55
|
expect(input.input.scrollWidth).to.equal(clean.input.scrollWidth);
|
|
55
56
|
});
|
|
57
|
+
|
|
58
|
+
it('submits on Enter only when submit-on-enter is set', async () => {
|
|
59
|
+
const table = await fixture<ZnDataTable>(html`
|
|
60
|
+
<zn-data-table>
|
|
61
|
+
<zn-filter-wrapper slot="filter-top">
|
|
62
|
+
<zn-input name="email"></zn-input>
|
|
63
|
+
</zn-filter-wrapper>
|
|
64
|
+
</zn-data-table>
|
|
65
|
+
`);
|
|
66
|
+
let refreshes = 0;
|
|
67
|
+
table.refresh = async () => { refreshes++; };
|
|
68
|
+
const wrapper = table.querySelector<ZnFilterWrapper>('zn-filter-wrapper')!;
|
|
69
|
+
const input = table.querySelector<ZnInput>('zn-input')!;
|
|
70
|
+
await input.updateComplete;
|
|
71
|
+
|
|
72
|
+
input.focus();
|
|
73
|
+
await sendKeys({type: 'a@b.com'});
|
|
74
|
+
await sendKeys({press: 'Enter'});
|
|
75
|
+
expect(refreshes).to.equal(0);
|
|
76
|
+
|
|
77
|
+
wrapper.submitOnEnter = true;
|
|
78
|
+
await sendKeys({press: 'Enter'});
|
|
79
|
+
expect(refreshes).to.equal(1);
|
|
80
|
+
expect(table.requestParams).to.deep.equal({email: 'a@b.com'});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('shows the submit button as processing until results load', async () => {
|
|
84
|
+
const table = await fixture<ZnDataTable>(html`
|
|
85
|
+
<zn-data-table>
|
|
86
|
+
<zn-filter-wrapper slot="filter-top">
|
|
87
|
+
<zn-input name="email"></zn-input>
|
|
88
|
+
<zn-button submit>Submit</zn-button>
|
|
89
|
+
</zn-filter-wrapper>
|
|
90
|
+
</zn-data-table>
|
|
91
|
+
`);
|
|
92
|
+
let finish!: () => void;
|
|
93
|
+
let refreshes = 0;
|
|
94
|
+
table.refresh = () => {
|
|
95
|
+
refreshes++;
|
|
96
|
+
return new Promise<void>(resolve => { finish = resolve; });
|
|
97
|
+
};
|
|
98
|
+
const button = table.querySelector<ZnButton>('zn-button')!;
|
|
99
|
+
await button.updateComplete;
|
|
100
|
+
const base = button.shadowRoot!.querySelector<HTMLButtonElement>('[part="base"]')!;
|
|
101
|
+
|
|
102
|
+
base.click();
|
|
103
|
+
base.click();
|
|
104
|
+
expect(refreshes).to.equal(1);
|
|
105
|
+
expect(button.processing).to.be.true;
|
|
106
|
+
expect(button.processingText).to.equal('Searching...');
|
|
107
|
+
|
|
108
|
+
finish();
|
|
109
|
+
await new Promise(resolve => setTimeout(resolve));
|
|
110
|
+
expect(button.processing).to.be.false;
|
|
111
|
+
});
|
|
56
112
|
});
|
|
@@ -171,6 +171,8 @@ export default class ZnFlowBuilder extends ZincElement {
|
|
|
171
171
|
@state() private _movingNodeId: string | null = null;
|
|
172
172
|
/** The "+" picker popover target (an open output, or a wire to insert into), if open. */
|
|
173
173
|
@state() private _picker: { x: number; y: number; target: PickerTarget } | null = null;
|
|
174
|
+
/** Where focus goes back to when the picker or branch editor closes. */
|
|
175
|
+
private _focusReturn: HTMLElement | null = null;
|
|
174
176
|
/** The node type currently being dragged from the steps panel, for the canvas drop preview. */
|
|
175
177
|
@state() private _draggingType: string | null = null;
|
|
176
178
|
|
|
@@ -338,12 +340,41 @@ export default class ZnFlowBuilder extends ZincElement {
|
|
|
338
340
|
|
|
339
341
|
private _onKeyDown = (e: KeyboardEvent) => {
|
|
340
342
|
if (e.key === 'Escape' && (this._movingNodeId || this._picker || this._selectedBranch)) {
|
|
343
|
+
const hadFocus = !!this.shadowRoot?.querySelector('.picker:focus-within, .inspector:focus-within');
|
|
341
344
|
this._movingNodeId = null;
|
|
342
345
|
this._picker = null;
|
|
343
346
|
this._selectedBranch = null;
|
|
347
|
+
if (hadFocus) void this._returnFocus(this._focusReturn);
|
|
344
348
|
}
|
|
345
349
|
};
|
|
346
350
|
|
|
351
|
+
private static _deepActiveElement() {
|
|
352
|
+
let el = document.activeElement;
|
|
353
|
+
while (el?.shadowRoot?.activeElement) el = el.shadowRoot.activeElement;
|
|
354
|
+
return el as HTMLElement | null;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
private _nodeCard(nodeId: string) {
|
|
358
|
+
const canvas = this.shadowRoot?.querySelector('zn-flow-canvas');
|
|
359
|
+
const node = [...(canvas?.shadowRoot?.querySelectorAll('zn-flow-node') ?? [])].find(n => n.node?.id === nodeId);
|
|
360
|
+
return node?.shadowRoot?.querySelector<HTMLElement>('.card');
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
private async _returnFocus(target: HTMLElement | null | undefined) {
|
|
364
|
+
await this.updateComplete;
|
|
365
|
+
if (target?.isConnected) target.focus();
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
private _closeInspector(nodeId: string) {
|
|
369
|
+
this._select(null);
|
|
370
|
+
void this._returnFocus(this._nodeCard(nodeId));
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
private _closeBranchEditor(nodeId: string) {
|
|
374
|
+
this._selectedBranch = null;
|
|
375
|
+
void this._returnFocus(this._focusReturn?.isConnected ? this._focusReturn : this._nodeCard(nodeId));
|
|
376
|
+
}
|
|
377
|
+
|
|
347
378
|
protected willUpdate(changed: PropertyValues) {
|
|
348
379
|
if (changed.has('nodeTypes') && this.nodeTypes?.length) {
|
|
349
380
|
this.registry.registerAll(this.nodeTypes);
|
|
@@ -974,6 +1005,7 @@ export default class ZnFlowBuilder extends ZincElement {
|
|
|
974
1005
|
}
|
|
975
1006
|
|
|
976
1007
|
private _onBranchPick = (e: CustomEvent<{ nodeId: string; port: string }>) => {
|
|
1008
|
+
this._focusReturn = ZnFlowBuilder._deepActiveElement();
|
|
977
1009
|
this._select(null);
|
|
978
1010
|
this._sideCollapsed = false;
|
|
979
1011
|
this._selectedBranch = {nodeId: e.detail.nodeId, port: e.detail.port};
|
|
@@ -1031,6 +1063,7 @@ export default class ZnFlowBuilder extends ZincElement {
|
|
|
1031
1063
|
};
|
|
1032
1064
|
|
|
1033
1065
|
private _onWirePick = (e: CustomEvent<{ connectionId: string; clientX: number; clientY: number }>) => {
|
|
1066
|
+
this._focusReturn = ZnFlowBuilder._deepActiveElement();
|
|
1034
1067
|
this._picker = {
|
|
1035
1068
|
x: e.detail.clientX,
|
|
1036
1069
|
y: e.detail.clientY,
|
|
@@ -1260,7 +1293,7 @@ export default class ZnFlowBuilder extends ZincElement {
|
|
|
1260
1293
|
<div class="inspector-head__title">${node.label ?? type?.label ?? node.type}</div>
|
|
1261
1294
|
<div class="inspector-head__type">${type?.label ?? node.type}</div>
|
|
1262
1295
|
</div>
|
|
1263
|
-
<button class="inspector-close" title="Close" @click="${() => this.
|
|
1296
|
+
<button class="inspector-close" title="Close" @click="${() => this._closeInspector(node.id)}">
|
|
1264
1297
|
<zn-icon src="x@lu" size="18"></zn-icon>
|
|
1265
1298
|
</button>
|
|
1266
1299
|
</div>
|
|
@@ -1337,7 +1370,7 @@ export default class ZnFlowBuilder extends ZincElement {
|
|
|
1337
1370
|
: `Branch of ${node.label ?? type?.label ?? node.type}`}
|
|
1338
1371
|
</div>
|
|
1339
1372
|
</div>
|
|
1340
|
-
<button class="inspector-close" title="Close" @click="${() =>
|
|
1373
|
+
<button class="inspector-close" title="Close" @click="${() => this._closeBranchEditor(node.id)}">
|
|
1341
1374
|
<zn-icon src="x@lu" size="18"></zn-icon>
|
|
1342
1375
|
</button>
|
|
1343
1376
|
</div>
|
|
@@ -1358,7 +1391,7 @@ export default class ZnFlowBuilder extends ZincElement {
|
|
|
1358
1391
|
.value="${branchConditions(port)}"
|
|
1359
1392
|
@flow-conditions-save="${(e: CustomEvent<{ conditions: FlowBranchConditions }>) =>
|
|
1360
1393
|
this._saveBranchConditions(node, port, e.detail.conditions)}"
|
|
1361
|
-
@flow-conditions-cancel="${() =>
|
|
1394
|
+
@flow-conditions-cancel="${() => this._closeBranchEditor(node.id)}"
|
|
1362
1395
|
></zn-flow-branch-conditions>`
|
|
1363
1396
|
: html`<p class="inspector-hint">This step type has no branch conditions.</p>`}
|
|
1364
1397
|
</div>
|
|
@@ -141,12 +141,6 @@
|
|
|
141
141
|
// rather than the navbar's default body colour.
|
|
142
142
|
--zn-active-nav-background: var(--zn-panel);
|
|
143
143
|
|
|
144
|
-
// Themes with a glass page tab bar (e.g. Aura) frost inactive tabs on every
|
|
145
|
-
// navbar under a zn-page — over the panel the translucent white just reads
|
|
146
|
-
// as white. Pin the standard tab tint instead.
|
|
147
|
-
--navbar-page-inactive-tab-background: rgb(var(--zn-color-tab));
|
|
148
|
-
--navbar-page-inactive-tab-filter: none;
|
|
149
|
-
|
|
150
144
|
border-right: 1px solid rgb(var(--zn-border-color));
|
|
151
145
|
|
|
152
146
|
// The registry-driven steps panel fills the column below the title block.
|
|
@@ -1181,11 +1181,19 @@ export default class ZnFlowCanvas extends ZincElement {
|
|
|
1181
1181
|
<span
|
|
1182
1182
|
class="branch-pill-port"
|
|
1183
1183
|
title="Start a branch"
|
|
1184
|
+
role="button"
|
|
1185
|
+
tabindex="0"
|
|
1186
|
+
aria-label="Start a branch"
|
|
1184
1187
|
@pointerdown="${(e: PointerEvent) => e.button === 0 && e.stopPropagation()}"
|
|
1185
1188
|
@click="${(e: Event) => {
|
|
1186
1189
|
e.stopPropagation();
|
|
1187
1190
|
this._onBranchPortClick(i.nodeId, i.portId);
|
|
1188
1191
|
}}"
|
|
1192
|
+
@keydown="${(e: KeyboardEvent) => {
|
|
1193
|
+
if (e.key !== 'Enter' && e.key !== ' ') return;
|
|
1194
|
+
e.preventDefault();
|
|
1195
|
+
(e.currentTarget as HTMLElement).click();
|
|
1196
|
+
}}"
|
|
1189
1197
|
></span>` : ''}
|
|
1190
1198
|
</div>
|
|
1191
1199
|
`
|
|
@@ -248,6 +248,11 @@
|
|
|
248
248
|
transform: translate(-50%, 50%) scale(1.35);
|
|
249
249
|
box-shadow: 0 0 0 4px color-mix(in srgb, rgb(var(--zn-color-primary)) 20%, transparent);
|
|
250
250
|
}
|
|
251
|
+
|
|
252
|
+
&:focus-visible {
|
|
253
|
+
outline: var(--zn-focus-ring);
|
|
254
|
+
outline-offset: 2px;
|
|
255
|
+
}
|
|
251
256
|
}
|
|
252
257
|
|
|
253
258
|
// Slides out from behind the pill on hover; deletes the branch and its wire.
|
|
@@ -372,8 +377,8 @@
|
|
|
372
377
|
position: absolute;
|
|
373
378
|
display: flex;
|
|
374
379
|
flex-direction: column;
|
|
375
|
-
background: #fef9c3;
|
|
376
|
-
border: 1px solid #fde68a;
|
|
380
|
+
background: var(--zn-flow-note-background, #fef9c3);
|
|
381
|
+
border: 1px solid var(--zn-flow-note-border, #fde68a);
|
|
377
382
|
border-radius: 4px;
|
|
378
383
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
|
|
379
384
|
|
|
@@ -385,7 +390,7 @@
|
|
|
385
390
|
height: 16px;
|
|
386
391
|
cursor: nwse-resize;
|
|
387
392
|
// Visual corner grip.
|
|
388
|
-
background: linear-gradient(135deg, transparent 0 50%, #d9c64a 50% 60%, transparent 60% 70%, #d9c64a 70% 80%, transparent 80%);
|
|
393
|
+
background: linear-gradient(135deg, transparent 0 50%, var(--zn-flow-note-fold, #d9c64a) 50% 60%, transparent 60% 70%, var(--zn-flow-note-fold, #d9c64a) 70% 80%, transparent 80%);
|
|
389
394
|
}
|
|
390
395
|
|
|
391
396
|
&__bar {
|
|
@@ -401,7 +406,7 @@
|
|
|
401
406
|
padding: 0;
|
|
402
407
|
font-size: 14px;
|
|
403
408
|
line-height: 1;
|
|
404
|
-
color: #92400e;
|
|
409
|
+
color: var(--zn-flow-note-meta-color, #92400e);
|
|
405
410
|
background: transparent;
|
|
406
411
|
cursor: pointer;
|
|
407
412
|
}
|
|
@@ -416,6 +421,6 @@
|
|
|
416
421
|
background: transparent;
|
|
417
422
|
font: inherit;
|
|
418
423
|
font-size: 0.8125rem;
|
|
419
|
-
color: #713f12;
|
|
424
|
+
color: var(--zn-flow-note-color, #713f12);
|
|
420
425
|
}
|
|
421
426
|
}
|
|
@@ -91,6 +91,13 @@ export default class ZnFlowNode extends ZincElement {
|
|
|
91
91
|
this._emit('flow-node-grab', {nodeId: this.node.id, clientX: e.clientX, clientY: e.clientY});
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
+
private _onBodyKeyDown = (e: KeyboardEvent) => {
|
|
95
|
+
// The node's menu trigger keeps its own keys
|
|
96
|
+
if (e.target !== e.currentTarget || (e.key !== 'Enter' && e.key !== ' ')) return;
|
|
97
|
+
e.preventDefault();
|
|
98
|
+
this._emit('flow-node-select', {nodeId: this.node.id});
|
|
99
|
+
};
|
|
100
|
+
|
|
94
101
|
private _action(action: 'delete' | 'duplicate' | 'move') {
|
|
95
102
|
this._emit('flow-node-action', {nodeId: this.node.id, action});
|
|
96
103
|
}
|
|
@@ -126,7 +133,9 @@ export default class ZnFlowNode extends ZincElement {
|
|
|
126
133
|
<div
|
|
127
134
|
part="base"
|
|
128
135
|
class="${classMap({card: true, selected: this.selected, error: this.error, 'link-target': this.linkTarget})}"
|
|
136
|
+
tabindex="0"
|
|
129
137
|
@pointerdown="${this._onBodyPointerDown}"
|
|
138
|
+
@keydown="${this._onBodyKeyDown}"
|
|
130
139
|
>
|
|
131
140
|
${inputs.length ? this._renderPorts(inputs, 'in') : ''}
|
|
132
141
|
|
|
@@ -159,6 +168,14 @@ export default class ZnFlowNode extends ZincElement {
|
|
|
159
168
|
<span
|
|
160
169
|
class="port port--out"
|
|
161
170
|
title="Start a branch"
|
|
171
|
+
role="button"
|
|
172
|
+
tabindex="0"
|
|
173
|
+
aria-label="Start a branch"
|
|
174
|
+
@keydown="${(e: KeyboardEvent) => {
|
|
175
|
+
if (e.key !== 'Enter' && e.key !== ' ') return;
|
|
176
|
+
e.preventDefault();
|
|
177
|
+
(e.currentTarget as HTMLElement).click();
|
|
178
|
+
}}"
|
|
162
179
|
@pointerdown="${(e: PointerEvent) => e.button === 0 && e.stopPropagation()}"
|
|
163
180
|
@click="${(e: Event) => {
|
|
164
181
|
e.stopPropagation();
|
|
@@ -35,6 +35,11 @@
|
|
|
35
35
|
border-color: rgb(var(--zn-color-border-active));
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
&:focus-visible {
|
|
39
|
+
outline: var(--zn-focus-ring);
|
|
40
|
+
outline-offset: 2px;
|
|
41
|
+
}
|
|
42
|
+
|
|
38
43
|
&.selected {
|
|
39
44
|
border-color: var(--node-accent);
|
|
40
45
|
box-shadow: 0 0 0 2px color-mix(in srgb, var(--node-accent) 35%, transparent);
|
|
@@ -157,6 +162,11 @@ zn-menu-item.danger {
|
|
|
157
162
|
background: var(--node-accent);
|
|
158
163
|
box-shadow: 0 0 0 4px color-mix(in srgb, var(--node-accent) 25%, transparent);
|
|
159
164
|
}
|
|
165
|
+
|
|
166
|
+
&:focus-visible {
|
|
167
|
+
outline: var(--zn-focus-ring);
|
|
168
|
+
outline-offset: 2px;
|
|
169
|
+
}
|
|
160
170
|
}
|
|
161
171
|
|
|
162
172
|
// Anchored at the card edge, at its horizontal position (set inline as left:%).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {type CSSResultGroup, html, unsafeCSS} from 'lit';
|
|
2
2
|
import {idSelector} from "../../utilities/query";
|
|
3
|
-
import {property} from 'lit/decorators.js';
|
|
3
|
+
import {property, state} from 'lit/decorators.js';
|
|
4
4
|
import ZincElement from '../../internal/zinc-element';
|
|
5
5
|
import ZnButton from "../button";
|
|
6
6
|
|
|
@@ -58,6 +58,51 @@ export default class ZnFormActions extends ZincElement {
|
|
|
58
58
|
/** The id of the form to act on. If omitted, the closest containing form is used. */
|
|
59
59
|
@property() form: string;
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Shows the submit button loading and ignores further submits until the console reports the request finished,
|
|
63
|
+
* so a slow save such as an upload can't be sent twice. Only for forms the console submits.
|
|
64
|
+
*/
|
|
65
|
+
@property({attribute: 'loading-on-submit', type: Boolean}) loadingOnSubmit = false;
|
|
66
|
+
|
|
67
|
+
@state() private submitting = false;
|
|
68
|
+
|
|
69
|
+
private watchedForm: HTMLFormElement | null = null;
|
|
70
|
+
|
|
71
|
+
connectedCallback() {
|
|
72
|
+
super.connectedCallback();
|
|
73
|
+
if (this.loadingOnSubmit) {
|
|
74
|
+
this.watchedForm = this.getForm();
|
|
75
|
+
this.watchedForm?.addEventListener('submit', this.handleFormSubmit, {capture: true});
|
|
76
|
+
this.watchedForm?.addEventListener('requested', this.handleRequested);
|
|
77
|
+
['complete', 'error', 'cancelled'].forEach(e => this.watchedForm?.addEventListener(e, this.handleDone));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
disconnectedCallback() {
|
|
82
|
+
this.watchedForm?.removeEventListener('submit', this.handleFormSubmit, {capture: true});
|
|
83
|
+
this.watchedForm?.removeEventListener('requested', this.handleRequested);
|
|
84
|
+
['complete', 'error', 'cancelled'].forEach(e => this.watchedForm?.removeEventListener(e, this.handleDone));
|
|
85
|
+
this.watchedForm = null;
|
|
86
|
+
super.disconnectedCallback();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Only the original submit is blocked; the console re-dispatches it as a composed event
|
|
90
|
+
private handleFormSubmit = (e: Event) => {
|
|
91
|
+
if (this.submitting && !e.composed) {
|
|
92
|
+
e.preventDefault();
|
|
93
|
+
e.stopImmediatePropagation();
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Set once the console sends the request, so a submit that validation stops doesn't stick
|
|
98
|
+
private handleRequested = () => {
|
|
99
|
+
this.submitting = true;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
private handleDone = () => {
|
|
103
|
+
this.submitting = false;
|
|
104
|
+
};
|
|
105
|
+
|
|
61
106
|
// The buttons live in this component's shadow root, so zn-button's own
|
|
62
107
|
// submit/reset handling can't find the form — resolve it from the host.
|
|
63
108
|
private getForm(): HTMLFormElement | null {
|
|
@@ -92,7 +137,8 @@ export default class ZnFormActions extends ZincElement {
|
|
|
92
137
|
<zn-button part="reset-button" panel-bg icon="${this.resetIcon}" @click="${this.handleReset}">
|
|
93
138
|
${this.resetText}
|
|
94
139
|
</zn-button>` : ''}
|
|
95
|
-
<zn-button part="submit-button" color="primary" icon="${this.submitIcon}" @click="${this.handleSubmit}"
|
|
140
|
+
<zn-button part="submit-button" color="primary" icon="${this.submitIcon}" @click="${this.handleSubmit}"
|
|
141
|
+
?loading=${this.submitting} ?disabled=${this.submitting} loading-text="${this.submitText}">
|
|
96
142
|
${this.submitText}
|
|
97
143
|
</zn-button>`;
|
|
98
144
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
display: flex;
|
|
6
6
|
justify-content: flex-end;
|
|
7
7
|
align-items: center;
|
|
8
|
-
gap: var(--zn-spacing-small);
|
|
8
|
+
gap: var(--zn-form-actions-gap, var(--zn-spacing-small));
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
// The spacer, not an auto margin, is what splits the two sides: an auto margin on every left-hand action would open
|
|
@@ -43,6 +43,9 @@ export default class ZnFormGroup extends ZincElement {
|
|
|
43
43
|
@property({ attribute: 'cols', type: Boolean }) forceCols = false;
|
|
44
44
|
@property({ attribute: 'layout', type: String }) layout = "1,2";
|
|
45
45
|
|
|
46
|
+
/** Labels the group like one of its fields and keeps it tight to them, for a section inside a form or dialog. */
|
|
47
|
+
@property({ type: Boolean }) compact = false;
|
|
48
|
+
|
|
46
49
|
@property({ attribute: 'pad', type: Boolean }) pad: boolean = false;
|
|
47
50
|
|
|
48
51
|
/** The scroller the label is moved against by hand; null while native sticky is enough. */
|
|
@@ -326,7 +329,10 @@ export default class ZnFormGroup extends ZincElement {
|
|
|
326
329
|
'form-control--has-label': hasLabel,
|
|
327
330
|
'form-control--has-label-tooltip': hasLabelTooltip,
|
|
328
331
|
'form-control--has-help-text': hasHelpText,
|
|
329
|
-
'form-control--pad': this.pad
|
|
332
|
+
'form-control--pad': this.pad,
|
|
333
|
+
'form-control--compact': this.compact,
|
|
334
|
+
'form-control--stacked': this.layout === '1',
|
|
335
|
+
'form-control--full': !hasLabel && !hasHelpText
|
|
330
336
|
})}"
|
|
331
337
|
aria-labelledby="label"
|
|
332
338
|
aria-describedby="help-text">
|
|
@@ -345,10 +351,11 @@ export default class ZnFormGroup extends ZincElement {
|
|
|
345
351
|
${hasLabelTooltip
|
|
346
352
|
? html`
|
|
347
353
|
<zn-tooltip class="form-control--label-tooltip">
|
|
348
|
-
<div slot="content">
|
|
354
|
+
<div slot="content" id="label-tooltip">
|
|
349
355
|
<slot name="label-tooltip">${this.labelTooltip}</slot>
|
|
350
356
|
</div>
|
|
351
|
-
<zn-icon src="info"
|
|
357
|
+
<zn-icon src="info" tabindex="0" role="img" aria-label="More information"
|
|
358
|
+
aria-describedby="label-tooltip"></zn-icon>
|
|
352
359
|
</zn-tooltip>`
|
|
353
360
|
: ''}
|
|
354
361
|
</label>` : html``}
|