@tylertech/forge 3.10.5 → 3.12.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/custom-elements.json +594 -226
- package/dist/app-bar/forge-app-bar.css +13 -5
- package/dist/button/forge-button.css +14 -6
- package/dist/checkbox/forge-checkbox.css +23 -17
- package/dist/chips/forge-chips.css +12 -4
- package/dist/field/forge-field.css +7 -5
- package/dist/floating-action-button/forge-floating-action-button.css +12 -6
- package/dist/forge.css +6 -1
- package/dist/icon-button/forge-icon-button.css +12 -4
- package/dist/lib.js +22 -22
- package/dist/lib.js.map +4 -4
- package/dist/list/forge-list.css +59 -3
- package/dist/radio/forge-radio.css +22 -12
- package/dist/skip-link/forge-skip-link.css +38 -32
- package/dist/state-layer/forge-state-layer.css +2 -0
- package/dist/switch/forge-switch.css +9 -5
- package/dist/table/forge-table.css +6 -1
- package/dist/vscode.html-custom-data.json +104 -79
- package/esm/accordion/accordion.d.ts +2 -0
- package/esm/accordion/accordion.js +2 -0
- package/esm/app-bar/app-bar/app-bar-adapter.js +2 -2
- package/esm/app-bar/app-bar/app-bar.d.ts +1 -1
- package/esm/app-bar/app-bar/app-bar.js +1 -1
- package/esm/app-bar/help-button/app-bar-help-button.d.ts +1 -1
- package/esm/app-bar/help-button/app-bar-help-button.js +1 -1
- package/esm/app-bar/menu-button/app-bar-menu-button.d.ts +1 -1
- package/esm/app-bar/menu-button/app-bar-menu-button.js +1 -1
- package/esm/app-bar/notification-button/app-bar-notification-button.d.ts +2 -0
- package/esm/app-bar/notification-button/app-bar-notification-button.js +2 -0
- package/esm/app-bar/profile-button/app-bar-profile-button-adapter.d.ts +2 -1
- package/esm/app-bar/profile-button/app-bar-profile-button-adapter.js +2 -0
- package/esm/app-bar/profile-button/app-bar-profile-button.d.ts +2 -0
- package/esm/app-bar/profile-button/app-bar-profile-button.js +2 -0
- package/esm/app-bar/search/app-bar-search.d.ts +2 -0
- package/esm/app-bar/search/app-bar-search.js +2 -0
- package/esm/autocomplete/autocomplete-core.js +16 -3
- package/esm/autocomplete/autocomplete.d.ts +2 -0
- package/esm/autocomplete/autocomplete.js +2 -0
- package/esm/avatar/avatar.d.ts +1 -1
- package/esm/avatar/avatar.js +1 -1
- package/esm/backdrop/backdrop.d.ts +2 -0
- package/esm/backdrop/backdrop.js +2 -0
- package/esm/badge/badge.d.ts +2 -0
- package/esm/badge/badge.js +2 -0
- package/esm/banner/banner.d.ts +1 -1
- package/esm/banner/banner.js +1 -1
- package/esm/button/base/base-button-adapter.js +2 -2
- package/esm/button/button.d.ts +1 -6
- package/esm/button/button.js +1 -6
- package/esm/button-area/button-area-adapter.js +2 -2
- package/esm/button-area/button-area.d.ts +1 -4
- package/esm/button-area/button-area.js +1 -4
- package/esm/button-toggle/button-toggle/button-toggle-adapter.js +2 -2
- package/esm/button-toggle/button-toggle/button-toggle.d.ts +2 -0
- package/esm/button-toggle/button-toggle/button-toggle.js +2 -0
- package/esm/button-toggle/button-toggle-group/button-toggle-group.d.ts +1 -1
- package/esm/button-toggle/button-toggle-group/button-toggle-group.js +1 -1
- package/esm/calendar/calendar-menu/calendar-menu.js +1 -1
- package/esm/calendar/calendar.d.ts +2 -0
- package/esm/calendar/calendar.js +3 -1
- package/esm/card/card.d.ts +2 -0
- package/esm/card/card.js +2 -0
- package/esm/chip-field/chip-field.d.ts +2 -0
- package/esm/chip-field/chip-field.js +2 -0
- package/esm/chips/chip/chip-adapter.d.ts +3 -0
- package/esm/chips/chip/chip-adapter.js +14 -4
- package/esm/chips/chip/chip-constants.d.ts +2 -0
- package/esm/chips/chip/chip-constants.js +2 -1
- package/esm/chips/chip/chip-core.d.ts +4 -0
- package/esm/chips/chip/chip-core.js +9 -0
- package/esm/chips/chip/chip.d.ts +6 -0
- package/esm/chips/chip/chip.js +10 -0
- package/esm/chips/chip-set/chip-set.d.ts +1 -1
- package/esm/chips/chip-set/chip-set.js +1 -1
- package/esm/circular-progress/circular-progress.d.ts +1 -2
- package/esm/circular-progress/circular-progress.js +1 -2
- package/esm/color-picker/color-picker.d.ts +2 -0
- package/esm/color-picker/color-picker.js +3 -1
- package/esm/core/utils/a11y-utils.js +17 -0
- package/esm/core/utils/utils.js +8 -2
- package/esm/date-picker/date-picker.d.ts +2 -0
- package/esm/date-picker/date-picker.js +2 -0
- package/esm/date-range-picker/date-range-picker.d.ts +2 -0
- package/esm/date-range-picker/date-range-picker.js +2 -0
- package/esm/deprecated/button/deprecated-button.js +3 -3
- package/esm/deprecated/icon-button/deprecated-icon-button.js +2 -2
- package/esm/dialog/dialog.d.ts +1 -1
- package/esm/dialog/dialog.js +1 -1
- package/esm/divider/divider.d.ts +1 -1
- package/esm/divider/divider.js +1 -1
- package/esm/drawer/base/base-drawer-adapter.d.ts +2 -0
- package/esm/drawer/base/base-drawer-adapter.js +3 -0
- package/esm/drawer/base/base-drawer-core.js +3 -0
- package/esm/drawer/drawer/drawer.d.ts +2 -0
- package/esm/drawer/drawer/drawer.js +3 -1
- package/esm/drawer/mini-drawer/mini-drawer.d.ts +2 -0
- package/esm/drawer/mini-drawer/mini-drawer.js +3 -1
- package/esm/drawer/modal-drawer/modal-drawer.d.ts +2 -0
- package/esm/drawer/modal-drawer/modal-drawer.js +3 -1
- package/esm/expansion-panel/expansion-panel.d.ts +1 -1
- package/esm/expansion-panel/expansion-panel.js +1 -1
- package/esm/field/field-adapter.js +2 -2
- package/esm/field/field-core.d.ts +3 -3
- package/esm/field/field.d.ts +1 -2
- package/esm/field/field.js +1 -2
- package/esm/file-picker/file-picker.d.ts +2 -3
- package/esm/file-picker/file-picker.js +2 -3
- package/esm/floating-action-button/floating-action-button.d.ts +1 -1
- package/esm/floating-action-button/floating-action-button.js +1 -1
- package/esm/focus-indicator/focus-indicator-constants.d.ts +1 -11
- package/esm/focus-indicator/focus-indicator-constants.js +2 -17
- package/esm/focus-indicator/focus-indicator.d.ts +53 -26
- package/esm/focus-indicator/focus-indicator.js +139 -62
- package/esm/focus-indicator/index.d.ts +0 -2
- package/esm/focus-indicator/index.js +0 -2
- package/esm/icon/icon.d.ts +1 -1
- package/esm/icon/icon.js +1 -1
- package/esm/icon-button/icon-button.d.ts +2 -0
- package/esm/icon-button/icon-button.js +2 -0
- package/esm/inline-message/inline-message.d.ts +1 -1
- package/esm/inline-message/inline-message.js +1 -1
- package/esm/keyboard-shortcut/keyboard-shortcut.d.ts +2 -0
- package/esm/keyboard-shortcut/keyboard-shortcut.js +2 -0
- package/esm/label/label.d.ts +1 -1
- package/esm/label/label.js +1 -1
- package/esm/label-value/label-value.d.ts +1 -1
- package/esm/label-value/label-value.js +1 -1
- package/esm/linear-progress/linear-progress.d.ts +1 -2
- package/esm/linear-progress/linear-progress.js +1 -2
- package/esm/list/list/list.d.ts +1 -1
- package/esm/list/list/list.js +2 -2
- package/esm/list/list-item/list-item-constants.js +1 -1
- package/esm/list/list-item/list-item-core.d.ts +2 -0
- package/esm/list/list-item/list-item-core.js +29 -6
- package/esm/list/list-item/list-item.d.ts +1 -0
- package/esm/list/list-item/list-item.js +2 -1
- package/esm/list-dropdown/list-dropdown-constants.d.ts +11 -1
- package/esm/list-dropdown/list-dropdown-constants.js +6 -1
- package/esm/list-dropdown/list-dropdown-utils.d.ts +3 -1
- package/esm/list-dropdown/list-dropdown-utils.js +69 -21
- package/esm/menu/menu-adapter.d.ts +2 -0
- package/esm/menu/menu-adapter.js +12 -8
- package/esm/menu/menu-constants.d.ts +1 -0
- package/esm/menu/menu-constants.js +3 -2
- package/esm/menu/menu-core.d.ts +5 -0
- package/esm/menu/menu-core.js +41 -2
- package/esm/menu/menu.d.ts +17 -0
- package/esm/menu/menu.js +15 -1
- package/esm/open-icon/open-icon.d.ts +2 -1
- package/esm/open-icon/open-icon.js +2 -1
- package/esm/overlay/overlay.d.ts +1 -2
- package/esm/overlay/overlay.js +1 -2
- package/esm/page-state/page-state.d.ts +2 -1
- package/esm/page-state/page-state.js +2 -1
- package/esm/paginator/paginator-core.d.ts +16 -0
- package/esm/paginator/paginator-core.js +29 -9
- package/esm/paginator/paginator.d.ts +38 -0
- package/esm/paginator/paginator.js +46 -0
- package/esm/popover/popover-adapter.js +1 -1
- package/esm/popover/popover-constants.d.ts +4 -0
- package/esm/popover/popover-constants.js +4 -2
- package/esm/popover/popover-core.d.ts +5 -1
- package/esm/popover/popover-core.js +13 -0
- package/esm/popover/popover.d.ts +6 -2
- package/esm/popover/popover.js +10 -2
- package/esm/profile-card/profile-card.d.ts +3 -0
- package/esm/profile-card/profile-card.js +3 -0
- package/esm/radio/radio/radio.d.ts +1 -2
- package/esm/radio/radio/radio.js +1 -2
- package/esm/scaffold/scaffold.d.ts +1 -1
- package/esm/scaffold/scaffold.js +1 -1
- package/esm/select/core/base-select-constants.d.ts +4 -0
- package/esm/select/core/base-select-core.d.ts +22 -2
- package/esm/select/core/base-select-core.js +217 -40
- package/esm/select/option/option.d.ts +2 -0
- package/esm/select/option/option.js +2 -0
- package/esm/select/option-group/option-group.d.ts +2 -0
- package/esm/select/option-group/option-group.js +2 -0
- package/esm/select/select/select-constants.d.ts +5 -0
- package/esm/select/select/select-constants.js +5 -2
- package/esm/select/select/select.d.ts +14 -2
- package/esm/select/select/select.js +23 -2
- package/esm/select/select-dropdown/select-dropdown.d.ts +2 -0
- package/esm/select/select-dropdown/select-dropdown.js +2 -0
- package/esm/skeleton/skeleton.d.ts +1 -1
- package/esm/skeleton/skeleton.js +1 -1
- package/esm/skip-link/skip-link.d.ts +1 -1
- package/esm/skip-link/skip-link.js +1 -1
- package/esm/slider/slider.d.ts +1 -1
- package/esm/slider/slider.js +1 -1
- package/esm/split-button/split-button.d.ts +1 -1
- package/esm/split-button/split-button.js +2 -2
- package/esm/split-view/split-view/split-view.d.ts +2 -0
- package/esm/split-view/split-view/split-view.js +2 -0
- package/esm/split-view/split-view-panel/split-view-panel.d.ts +2 -0
- package/esm/split-view/split-view-panel/split-view-panel.js +3 -1
- package/esm/stack/stack.d.ts +1 -8
- package/esm/stack/stack.js +1 -8
- package/esm/state-layer/state-layer.d.ts +1 -1
- package/esm/state-layer/state-layer.js +2 -2
- package/esm/stepper/step/step.d.ts +2 -0
- package/esm/stepper/step/step.js +3 -1
- package/esm/stepper/stepper/stepper.d.ts +2 -0
- package/esm/stepper/stepper/stepper.js +2 -0
- package/esm/table/table-adapter.d.ts +4 -4
- package/esm/table/table-adapter.js +4 -4
- package/esm/table/table-core.js +2 -2
- package/esm/table/table-utils.d.ts +2 -2
- package/esm/table/table-utils.js +25 -18
- package/esm/table/table.d.ts +3 -1
- package/esm/table/table.js +4 -1
- package/esm/tabs/tab/tab-adapter.js +2 -2
- package/esm/tabs/tab/tab.d.ts +2 -0
- package/esm/tabs/tab/tab.js +2 -0
- package/esm/tabs/tab-bar/tab-bar.d.ts +1 -1
- package/esm/tabs/tab-bar/tab-bar.js +1 -1
- package/esm/text-field/text-field-adapter.d.ts +6 -4
- package/esm/text-field/text-field-adapter.js +11 -4
- package/esm/text-field/text-field-core.d.ts +4 -0
- package/esm/text-field/text-field-core.js +13 -2
- package/esm/text-field/text-field.d.ts +1 -1
- package/esm/text-field/text-field.js +1 -1
- package/esm/time-picker/time-picker-adapter.js +1 -0
- package/esm/time-picker/time-picker-core.js +3 -3
- package/esm/time-picker/time-picker.d.ts +2 -0
- package/esm/time-picker/time-picker.js +2 -0
- package/esm/toast/toast-adapter.d.ts +20 -0
- package/esm/toast/toast-adapter.js +30 -0
- package/esm/toast/toast-core.d.ts +17 -0
- package/esm/toast/toast-core.js +66 -0
- package/esm/toast/toast.d.ts +9 -2
- package/esm/toast/toast.js +10 -1
- package/esm/toolbar/toolbar.d.ts +1 -3
- package/esm/toolbar/toolbar.js +1 -3
- package/esm/tooltip/tooltip-adapter.d.ts +6 -0
- package/esm/tooltip/tooltip-adapter.js +9 -0
- package/esm/tooltip/tooltip-constants.d.ts +1 -0
- package/esm/tooltip/tooltip-constants.js +2 -1
- package/esm/tooltip/tooltip-core.d.ts +20 -0
- package/esm/tooltip/tooltip-core.js +96 -2
- package/esm/tooltip/tooltip.d.ts +1 -1
- package/esm/tooltip/tooltip.js +2 -2
- package/esm/view-switcher/view/view.d.ts +2 -0
- package/esm/view-switcher/view/view.js +2 -0
- package/esm/view-switcher/view-switcher.d.ts +2 -0
- package/esm/view-switcher/view-switcher.js +2 -0
- package/package.json +4 -4
- package/sass/focus-indicator/focus-indicator.scss +1 -1
- package/sass/icon-button/forge-icon-button.scss +3 -3
- package/sass/list/forge-list.scss +6 -6
- package/sass/state-layer/_core.scss +2 -0
- package/sass/table/_core.scss +13 -1
- package/sass/tooltip/_core.scss +0 -2
- package/esm/focus-indicator/focus-indicator-adapter.d.ts +0 -29
- package/esm/focus-indicator/focus-indicator-adapter.js +0 -37
- package/esm/focus-indicator/focus-indicator-core.d.ts +0 -48
- package/esm/focus-indicator/focus-indicator-core.js +0 -129
|
@@ -64,6 +64,7 @@ declare const ListItemComponent_base: import("../..").AbstractConstructor<import
|
|
|
64
64
|
* @slot tertiary-text - The tertiary text.
|
|
65
65
|
* @slot start - The start content.
|
|
66
66
|
* @slot end - The end element.
|
|
67
|
+
* @slot additional-content - Additional content that appears below the main list item interactive area.
|
|
67
68
|
*
|
|
68
69
|
* @csspart root - The root container element.
|
|
69
70
|
* @csspart text-container - The container for the text content.
|
|
@@ -13,7 +13,7 @@ import { FocusIndicatorComponent } from '../../focus-indicator';
|
|
|
13
13
|
import { WithElementInternals } from '../../core/mixins/internals/with-element-internals';
|
|
14
14
|
import { WithDefaultAria } from '../../core/mixins/internals/with-default-aria';
|
|
15
15
|
import { BaseComponent } from '../../core/base/base-component';
|
|
16
|
-
const template = '<template><div class=\"forge-list-item\" part=\"root\"><slot name=\"start\"><slot name=\"leading\"></slot></slot><div class=\"text-container\" part=\"text-container\"><slot></slot><slot name=\"secondary-text\"></slot><slot name=\"tertiary-text\"></slot></div><slot name=\"end\"><slot name=\"trailing\"></slot></slot></div></template>';
|
|
16
|
+
const template = '<template><div class=\"forge-list-item\" part=\"root\"><slot name=\"start\"><slot name=\"leading\"></slot></slot><div class=\"text-container\" part=\"text-container\"><slot></slot><slot name=\"secondary-text\"></slot><slot name=\"tertiary-text\"></slot></div><slot name=\"end\"><slot name=\"trailing\"></slot></slot></div><slot name=\"additional-content\"></slot></template>';
|
|
17
17
|
const styles = ':host{--_list-item-indent:var(--forge-list-item-indent, var(--forge-spacing-xxlarge, 48px));--_list-item-dense-indent:var(--forge-list-item-dense-indent, var(--forge-spacing-xxlarge, 48px));--_list-item-disabled-cursor:var(--forge-list-item-disabled-cursor, not-allowed)}:host{display:block;outline:0}:host([hidden]){display:none}.forge-list-item{--_list-item-background:var(--forge-list-item-background, transparent);--_list-item-shape:var(--forge-list-item-shape, 0);--_list-item-padding:var(--forge-list-item-padding, 0 var(--forge-spacing-medium, 16px));--_list-item-margin:var(--forge-list-item-margin, 0);--_list-item-height:var(--forge-list-item-height, 48px);--_list-item-dense-height:var(--forge-list-item-dense-height, 32px);--_list-item-cursor:var(--forge-list-item-cursor, pointer);--_list-item-gap:var(--forge-list-item-gap, var(--forge-spacing-large, 24px));--_list-item-text-color:var(--forge-list-item-text-color, var(--forge-theme-text-medium, rgba(0, 0, 0, 0.6)));--_list-item-text-font-size:var(--forge-list-item-text-font-size, var(--forge-typography-body2-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-font-size-scale, 1))));--_list-item-text-font-weight:var(--forge-list-item-text-font-weight, var(--forge-typography-body2-font-weight, 400));--_list-item-text-line-height:var(--forge-list-item-text-line-height, 1.5rem);--_list-item-selected-color:var(--forge-list-item-selected-color, var(--forge-theme-primary, #3f51b5));--_list-item-selected-background:var(--forge-list-item-selected-background, var(--_list-item-selected-color));--_list-item-selected-opacity:var(--forge-list-item-selected-opacity, 0.08);--_list-item-selected-start-color:var(--forge-list-item-selected-start-color, var(--_list-item-selected-color));--_list-item-selected-end-color:var(--forge-list-item-selected-end-color, var(--_list-item-selected-color));--_list-item-selected-text-color:var(--forge-list-item-selected-text-color, var(--forge-theme-text-medium, rgba(0, 0, 0, 0.6)));--_list-item-disabled-opacity:var(--forge-list-item-disabled-opacity, 0.38);--_list-item-one-line-height:var(--forge-list-item-one-line-height, var(--_list-item-height));--_list-item-two-line-height:var(--forge-list-item-two-line-height, var(--forge-list-item-height, 72px));--_list-item-three-line-height:var(--forge-list-item-three-line-height, var(--forge-list-item-height, 88px));--_list-item-dense-one-line-height:var(--forge-list-item-dense-one-line-height, var(--_list-item-dense-height));--_list-item-dense-two-line-height:var(--forge-list-item-dense-two-line-height, var(--forge-list-item-dense-height, 56px));--_list-item-dense-three-line-height:var(--forge-list-item-dense-three-line-height, var(--forge-list-item-dense-height, 72px));--_list-item-dense-font-size:var(--forge-list-item-dense-font-size, 0.875rem);--_list-item-dense-gap:var(--forge-list-item-dense-gap, var(--forge-spacing-xsmall, 8px));--_list-item-start-selected-color:var(--forge-list-item-start-selected-color, var(--_list-item-selected-color));--_list-item-end-selected-color:var(--forge-list-item-end-selected-color, var(--_list-item-selected-color));--_list-item-wrap-padding:var(--forge-list-item-wrap-padding, var(--forge-spacing-xsmall, 8px) var(--forge-spacing-medium, 16px))}.forge-list-item{position:relative;display:flex;gap:var(--_list-item-gap);align-items:center;box-sizing:border-box;outline:0;text-decoration:none;border-radius:var(--_list-item-shape);-webkit-tap-highlight-color:transparent;background-color:var(--_list-item-background);height:var(--_list-item-height);min-height:var(--_list-item-height);padding:var(--_list-item-padding);margin:var(--_list-item-margin)}.forge-list-item.interactive{cursor:var(--_list-item-cursor)}.forge-list-item.disabled{cursor:var(--_list-item-disabled-cursor);opacity:var(--_list-item-disabled-opacity)}.forge-list-item.disabled ::slotted(button){cursor:var(--_list-item-disabled-cursor)}.anchor{position:absolute;inset:0}:host([two-line]) .forge-list-item{height:var(--_list-item-two-line-height);min-height:var(--_list-item-two-line-height)}:host([three-line]) .forge-list-item{height:var(--_list-item-three-line-height);min-height:var(--_list-item-three-line-height)}:host([dense]) .forge-list-item{--_list-item-gap:var(--_list-item-dense-gap);height:var(--_list-item-dense-one-line-height);min-height:var(--_list-item-dense-one-line-height)}:host([dense]) .text-container{font-size:var(--_list-item-dense-font-size)}:host([dense][indented]){margin-inline-start:var(--_list-item-dense-indent)}:host([dense][two-line]) .forge-list-item{height:var(--_list-item-dense-two-line-height);min-height:var(--_list-item-dense-two-line-height)}:host([dense][three-line]) .forge-list-item{height:var(--_list-item-dense-three-line-height);min-height:var(--_list-item-dense-three-line-height)}:host([selected]) .forge-list-item{color:var(--_list-item-selected-color)}:host([selected]) .forge-list-item::before{content:\"\";position:absolute;inset:0;border-radius:inherit;opacity:var(--_list-item-selected-opacity);background-color:var(--_list-item-selected-background);pointer-events:none}:host([selected]) .forge-list-item ::slotted([slot=end]),:host([selected]) .forge-list-item ::slotted([slot=leading]),:host([selected]) .forge-list-item ::slotted([slot=start]),:host([selected]) .forge-list-item ::slotted([slot=trailing]){color:var(--_list-item-selected-color);isolation:isolate}:host([selected]) .forge-list-item ::slotted([slot=leading]),:host([selected]) .forge-list-item ::slotted([slot=start]){color:var(--_list-item-start-selected-color)}:host([selected]) .forge-list-item ::slotted([slot=end]),:host([selected]) .forge-list-item ::slotted([slot=trailing]){color:var(--_list-item-end-selected-color)}:host([selected]) .text-container{color:var(--_list-item-selected-color)}:host([selected]) forge-state-layer{--forge-state-layer-color:var(--_list-item-selected-color)}:host([indented]) .forge-list-item{margin-inline-start:var(--_list-item-indent)}.text-container{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--forge-typography-body2-font-family, var(--forge-typography-font-family, \"Roboto\", sans-serif));letter-spacing:var(--forge-typography-body2-letter-spacing, .015625em);text-transform:var(--forge-typography-body2-text-transform,inherit);text-decoration:var(--forge-typography-body2-text-decoration,inherit);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;box-sizing:border-box;isolation:isolate;font-size:var(--_list-item-text-font-size);font-weight:var(--_list-item-text-font-weight);line-height:var(--_list-item-text-line-height);flex:1;contain:layout}slot[name=secondary-text]::slotted(*),slot[name=tertiary-text]::slotted(*){-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--forge-typography-body1-font-family, var(--forge-typography-font-family, \"Roboto\", sans-serif));font-size:var(--forge-typography-body1-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-font-size-scale, .875)));font-weight:var(--forge-typography-body1-font-weight,400);line-height:var(--forge-typography-body1-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-line-height-scale, 1.125)));letter-spacing:var(--forge-typography-body1-letter-spacing, .0357142857em);text-transform:var(--forge-typography-body1-text-transform,inherit);text-decoration:var(--forge-typography-body1-text-decoration,inherit);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--_list-item-text-color);display:block}:host([selected]) slot[name=secondary-text]::slotted(*),:host([selected]) slot[name=tertiary-text]::slotted(*){color:var(--_list-item-selected-text-color)}::slotted(:is(button:not([slot]),[forge-list-item-button])){appearance:none;cursor:var(--_list-item-cursor);border:none;padding-block:0;padding-inline:0;margin:0;box-sizing:border-box;width:100%;background:0 0;color:inherit;outline:0;font:inherit;user-select:auto;text-align:inherit;letter-spacing:inherit;word-spacing:inherit;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;display:block}::slotted(a){outline:0;color:inherit!important;text-decoration:none!important}::slotted([slot=end]),::slotted([slot=leading]),::slotted([slot=start]),::slotted([slot=trailing]){color:var(--_list-item-text-color);display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;fill:currentColor}:host(:not([noninteractive])) ::slotted(:is(forge-checkbox,forge-radio,forge-switch):is([slot=start],[slot=end],[slot=leading],[slot=trailing]):not([forge-ignore])){--forge-focus-indicator-display:none;--forge-state-layer-display:none}:host([selected]) ::slotted([slot=leading]),:host([selected]) ::slotted([slot=start]){color:var(--_list-item-start-selected-color)}:host([selected]) ::slotted([slot=end]),:host([selected]) ::slotted([slot=trailing]){color:var(--_list-item-end-selected-color)}:host([wrap]) .forge-list-item{--_list-item-padding:var(--_list-item-wrap-padding);height:auto}:host([wrap]) .text-container{white-space:normal;overflow:visible;text-overflow:clip;line-height:normal}:host([wrap]) ::slotted(:is(button,[role=button][tabindex],[forge-list-item-button])){white-space:normal}:host([wrap]) slot[name=secondary-text]::slotted(*),:host([wrap]) slot[name=tertiary-text]::slotted(*){white-space:normal;overflow:visible;text-overflow:clip;line-height:normal}forge-focus-indicator{z-index:1;--forge-focus-indicator-shape:calc(var(--forge-shape-medium, 4px) * var(--forge-shape-factor, 1))}forge-state-layer{border-radius:inherit}';
|
|
18
18
|
/**
|
|
19
19
|
* @tag forge-list-item
|
|
@@ -49,6 +49,7 @@ const styles = ':host{--_list-item-indent:var(--forge-list-item-indent, var(--fo
|
|
|
49
49
|
* @slot tertiary-text - The tertiary text.
|
|
50
50
|
* @slot start - The start content.
|
|
51
51
|
* @slot end - The end element.
|
|
52
|
+
* @slot additional-content - Additional content that appears below the main list item interactive area.
|
|
52
53
|
*
|
|
53
54
|
* @csspart root - The root container element.
|
|
54
55
|
* @csspart text-container - The container for the text content.
|
|
@@ -7,6 +7,7 @@ import type { IIconComponent } from '../icon';
|
|
|
7
7
|
import type { IOverlayOffset, OverlayFlipState, OverlayShiftState } from '../overlay/overlay-constants';
|
|
8
8
|
import { PositionPlacement } from '../core/utils/position-utils';
|
|
9
9
|
import { TooltipPlacement, TooltipType } from '../tooltip';
|
|
10
|
+
import type { PopoverAnchorAccessibility } from '../popover/popover-constants';
|
|
10
11
|
export declare const LIST_DROPDOWN_CONSTANTS: {
|
|
11
12
|
observedAttributes: {
|
|
12
13
|
POPUP_CLASSES: string;
|
|
@@ -39,12 +40,16 @@ export declare const LIST_DROPDOWN_CONSTANTS: {
|
|
|
39
40
|
classes: {
|
|
40
41
|
GROUP_WRAPPER: string;
|
|
41
42
|
};
|
|
43
|
+
selectAllOption: {
|
|
44
|
+
VALUE: string;
|
|
45
|
+
LABEL: string;
|
|
46
|
+
};
|
|
42
47
|
};
|
|
43
48
|
export type ListDropdownOptionBuilder<T = HTMLElement> = (option: IListDropdownOption, parentElement: T) => HTMLElement | string | void;
|
|
44
49
|
export type ListDropdownHeaderBuilder = () => HTMLElement;
|
|
45
50
|
export type ListDropdownFooterBuilder = () => HTMLElement;
|
|
46
51
|
export type ListDropdownOptionGroupBuilder<T = any> = (option: IListDropdownOptionGroup<T>) => HTMLElement | string;
|
|
47
|
-
export type ListDropdownTransformCallback = (label: string) => string | HTMLElement;
|
|
52
|
+
export type ListDropdownTransformCallback = (label: string, option?: IListDropdownOption, isSelected?: boolean) => string | HTMLElement;
|
|
48
53
|
export type ListDropdownIconType = 'font' | 'component';
|
|
49
54
|
export interface IBaseListDropdownOption<T = any> {
|
|
50
55
|
value: T;
|
|
@@ -84,6 +89,8 @@ export interface IListDropdownConfig<T = any> {
|
|
|
84
89
|
options: Array<IListDropdownOption | IListDropdownOptionGroup>;
|
|
85
90
|
selectCallback: (value: T) => void;
|
|
86
91
|
activeChangeCallback?: (id: string) => void;
|
|
92
|
+
showSelectAll?: boolean;
|
|
93
|
+
selectAllLabel?: string;
|
|
87
94
|
closeCallback?: () => void;
|
|
88
95
|
syncWidth?: boolean;
|
|
89
96
|
constrainViewportWidth?: boolean;
|
|
@@ -115,6 +122,7 @@ export interface IListDropdownConfig<T = any> {
|
|
|
115
122
|
footerBuilder?: ListDropdownFooterBuilder;
|
|
116
123
|
cascade?: boolean;
|
|
117
124
|
cascadingElementFactory?: (config: IListDropdownCascadingElementFactoryConfig) => HTMLElement;
|
|
125
|
+
anchorAccessibility?: PopoverAnchorAccessibility;
|
|
118
126
|
}
|
|
119
127
|
export interface IListDropdownCascadingElementFactoryConfig {
|
|
120
128
|
index: number;
|
|
@@ -141,4 +149,6 @@ export interface ListDropdownTooltipConfig {
|
|
|
141
149
|
offset?: number;
|
|
142
150
|
anchor?: string;
|
|
143
151
|
anchorElement?: HTMLElement;
|
|
152
|
+
visibilityMode?: ListDropdownTooltipVisibilityMode;
|
|
144
153
|
}
|
|
154
|
+
export type ListDropdownTooltipVisibilityMode = 'always' | 'overflow-only';
|
|
@@ -25,10 +25,15 @@ const attributes = {
|
|
|
25
25
|
const classes = {
|
|
26
26
|
GROUP_WRAPPER: 'forge-list-dropdown__group-wrapper'
|
|
27
27
|
};
|
|
28
|
+
const selectAllOption = {
|
|
29
|
+
VALUE: '__forge_select_all__',
|
|
30
|
+
LABEL: 'Select All'
|
|
31
|
+
};
|
|
28
32
|
export const LIST_DROPDOWN_CONSTANTS = {
|
|
29
33
|
observedAttributes,
|
|
30
34
|
attributes,
|
|
31
|
-
classes
|
|
35
|
+
classes,
|
|
36
|
+
selectAllOption
|
|
32
37
|
};
|
|
33
38
|
export const DEFAULT_LIST_DROPDOWN_CONFIG = {
|
|
34
39
|
options: [],
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { ILinearProgressComponent } from '../linear-progress';
|
|
7
7
|
import { IListComponent } from '../list/list';
|
|
8
8
|
import { IPopoverComponent } from '../popover/popover';
|
|
9
|
-
import { IListDropdownOpenConfig, IListDropdownOption, IListDropdownOptionGroup, ListDropdownAsyncStyle } from './list-dropdown-constants';
|
|
9
|
+
import { IListDropdownOpenConfig, IListDropdownOption, IListDropdownOptionGroup, ListDropdownAsyncStyle, ListDropdownTooltipConfig } from './list-dropdown-constants';
|
|
10
10
|
export declare enum ListDropdownOptionType {
|
|
11
11
|
Option = 0,
|
|
12
12
|
Group = 1
|
|
@@ -24,6 +24,8 @@ export declare function createList(config: IListDropdownOpenConfig): IListCompon
|
|
|
24
24
|
* @param config
|
|
25
25
|
*/
|
|
26
26
|
export declare function createListItems(config: IListDropdownOpenConfig, listElement: IListComponent, options?: Array<IListDropdownOption | IListDropdownOptionGroup>, startIndex?: number, renderSelected?: boolean): void;
|
|
27
|
+
export declare function createListItemTooltip(tooltip: ListDropdownTooltipConfig, configId: string, optionIdIndex: number, listItemElement: HTMLElement, buttonElement: HTMLElement): HTMLElement;
|
|
28
|
+
export declare function asyncCreateListItemTooltipIfTextOverflows(tooltip: ListDropdownTooltipConfig, configId: string, optionIdIndex: number, listItemElement: HTMLElement, buttonElement: HTMLElement, secondaryLabelElement: HTMLElement): Promise<void>;
|
|
27
29
|
export declare function createCheckboxElement(selected: boolean): HTMLElement;
|
|
28
30
|
export declare function createAsyncElement(asyncStyle?: ListDropdownAsyncStyle): HTMLElement;
|
|
29
31
|
export declare function createBusyElement(): ILinearProgressComponent;
|
|
@@ -11,6 +11,7 @@ import { LIST_CONSTANTS } from '../list/list';
|
|
|
11
11
|
import { POPOVER_CONSTANTS } from '../popover';
|
|
12
12
|
import { SKELETON_CONSTANTS } from '../skeleton';
|
|
13
13
|
import { ListDropdownAsyncStyle, ListDropdownType, LIST_DROPDOWN_CONSTANTS } from './list-dropdown-constants';
|
|
14
|
+
import { frame } from '../core/utils/utils';
|
|
14
15
|
export var ListDropdownOptionType;
|
|
15
16
|
(function (ListDropdownOptionType) {
|
|
16
17
|
ListDropdownOptionType[ListDropdownOptionType["Option"] = 0] = "Option";
|
|
@@ -66,6 +67,9 @@ export function createPopupDropdown(config, targetElement) {
|
|
|
66
67
|
if (config.popupShift !== undefined) {
|
|
67
68
|
popoverElement.shift = config.popupShift;
|
|
68
69
|
}
|
|
70
|
+
if (config.anchorAccessibility) {
|
|
71
|
+
popoverElement.anchorAccessibility = config.anchorAccessibility;
|
|
72
|
+
}
|
|
69
73
|
// Set the animations based on our type
|
|
70
74
|
if (config.type === ListDropdownType.None) {
|
|
71
75
|
popoverElement.animationType = 'none';
|
|
@@ -97,8 +101,35 @@ export function createList(config) {
|
|
|
97
101
|
* @param config
|
|
98
102
|
*/
|
|
99
103
|
export function createListItems(config, listElement, options, startIndex = 0, renderSelected = true) {
|
|
104
|
+
// Add select all option if enabled and in multiple mode
|
|
105
|
+
let optionsToRender = options || config.options;
|
|
106
|
+
if (config.showSelectAll && config.multiple && startIndex === 0) {
|
|
107
|
+
const selectAllOption = {
|
|
108
|
+
value: LIST_DROPDOWN_CONSTANTS.selectAllOption.VALUE,
|
|
109
|
+
label: config.selectAllLabel || LIST_DROPDOWN_CONSTANTS.selectAllOption.LABEL
|
|
110
|
+
};
|
|
111
|
+
const dividerOption = {
|
|
112
|
+
value: '',
|
|
113
|
+
label: '',
|
|
114
|
+
divider: true
|
|
115
|
+
};
|
|
116
|
+
// Inject select all at the beginning
|
|
117
|
+
if (isListDropdownOptionType(optionsToRender, ListDropdownOptionType.Group)) {
|
|
118
|
+
const optionGroups = optionsToRender;
|
|
119
|
+
if (optionGroups.length > 0) {
|
|
120
|
+
optionGroups[0] = { ...optionGroups[0], options: [selectAllOption, dividerOption, ...optionGroups[0].options] };
|
|
121
|
+
optionsToRender = optionGroups;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
optionsToRender = [{ text: '', options: [selectAllOption, dividerOption] }];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
optionsToRender = [selectAllOption, dividerOption, ...optionsToRender];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
100
131
|
// Ensure the options are provided in the form a group (if no groups provided, then we have one anonymous group of options)
|
|
101
|
-
const groups = getOptionsByGroup(
|
|
132
|
+
const groups = getOptionsByGroup(optionsToRender);
|
|
102
133
|
const flatOptions = getFlattenedOptions(groups);
|
|
103
134
|
const limitOptions = config.optionLimit ? true : false;
|
|
104
135
|
let optionLimit = config.optionLimit || 0;
|
|
@@ -193,7 +224,7 @@ export function createListItems(config, listElement, options, startIndex = 0, re
|
|
|
193
224
|
buttonElement.textContent = option.label || '';
|
|
194
225
|
}
|
|
195
226
|
else {
|
|
196
|
-
const result = config.transform(option.label);
|
|
227
|
+
const result = config.transform(option.label, option, isSelected);
|
|
197
228
|
if (typeof result === 'string') {
|
|
198
229
|
buttonElement.textContent = result;
|
|
199
230
|
}
|
|
@@ -202,27 +233,9 @@ export function createListItems(config, listElement, options, startIndex = 0, re
|
|
|
202
233
|
}
|
|
203
234
|
}
|
|
204
235
|
}
|
|
205
|
-
|
|
206
|
-
if (option.tooltip) {
|
|
207
|
-
const { text, type = 'presentation', ...restConfig } = option.tooltip;
|
|
208
|
-
const tooltipElement = document.createElement('forge-tooltip');
|
|
209
|
-
tooltipElement.id = `list-dropdown-option-${config.id}-${optionIdIndex++}-tooltip`;
|
|
210
|
-
tooltipElement.textContent = option.tooltip.text;
|
|
211
|
-
// We always anchor to the list item element unless an anchor element is provided
|
|
212
|
-
if (!option.tooltip.anchor && !option.tooltip.anchorElement) {
|
|
213
|
-
tooltipElement.anchorElement = listItemElement;
|
|
214
|
-
}
|
|
215
|
-
// We need to attach the tooltip ARIA attributes to the button element, not the anchor element
|
|
216
|
-
if (type === 'label' || type === 'description') {
|
|
217
|
-
const a11yAttr = type === 'label' ? 'aria-labelledby' : 'aria-describedby';
|
|
218
|
-
buttonElement.setAttribute(a11yAttr, tooltipElement.id);
|
|
219
|
-
}
|
|
220
|
-
Object.assign(tooltipElement, restConfig);
|
|
221
|
-
listItemElement.appendChild(tooltipElement);
|
|
222
|
-
}
|
|
236
|
+
const secondaryLabelElement = document.createElement('span');
|
|
223
237
|
// Check for secondary (subtitle) text
|
|
224
238
|
if (option.secondaryLabel) {
|
|
225
|
-
const secondaryLabelElement = document.createElement('span');
|
|
226
239
|
secondaryLabelElement.slot = 'secondary-text';
|
|
227
240
|
secondaryLabelElement.textContent = option.secondaryLabel;
|
|
228
241
|
secondaryLabelElement.id = `list-dropdown-option-${config.id}-${optionIdIndex++}-secondary`;
|
|
@@ -230,6 +243,16 @@ export function createListItems(config, listElement, options, startIndex = 0, re
|
|
|
230
243
|
listItemElement.appendChild(secondaryLabelElement);
|
|
231
244
|
buttonElement.setAttribute('aria-describedby', secondaryLabelElement.id);
|
|
232
245
|
}
|
|
246
|
+
// Check for a tooltip configuration
|
|
247
|
+
if (option.tooltip) {
|
|
248
|
+
if (!isDefined(option.tooltip?.visibilityMode) || option.tooltip?.visibilityMode === 'always') {
|
|
249
|
+
const tooltipElement = createListItemTooltip(option.tooltip, config.id, optionIdIndex, listItemElement, buttonElement);
|
|
250
|
+
listItemElement.appendChild(tooltipElement);
|
|
251
|
+
}
|
|
252
|
+
else if (option.tooltip?.visibilityMode === 'overflow-only') {
|
|
253
|
+
asyncCreateListItemTooltipIfTextOverflows(option.tooltip, config.id, optionIdIndex, listItemElement, buttonElement, secondaryLabelElement);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
233
256
|
// If multiple selections are enabled then we need to create and append a leading checkbox element
|
|
234
257
|
if (config.multiple) {
|
|
235
258
|
const checkboxElement = createCheckboxElement(isSelected);
|
|
@@ -303,6 +326,31 @@ export function createListItems(config, listElement, options, startIndex = 0, re
|
|
|
303
326
|
}
|
|
304
327
|
}
|
|
305
328
|
}
|
|
329
|
+
export function createListItemTooltip(tooltip, configId, optionIdIndex, listItemElement, buttonElement) {
|
|
330
|
+
const { text, type = 'presentation', ...restConfig } = tooltip;
|
|
331
|
+
const tooltipElement = document.createElement('forge-tooltip');
|
|
332
|
+
tooltipElement.id = `list-dropdown-option-${configId}-${optionIdIndex++}-tooltip`;
|
|
333
|
+
tooltipElement.textContent = tooltip.text;
|
|
334
|
+
// We always anchor to the list item element unless an anchor element is provided
|
|
335
|
+
if (!tooltip.anchor && !tooltip.anchorElement) {
|
|
336
|
+
tooltipElement.anchorElement = listItemElement;
|
|
337
|
+
}
|
|
338
|
+
// We need to attach the tooltip ARIA attributes to the button element, not the anchor element
|
|
339
|
+
if (type === 'label' || type === 'description') {
|
|
340
|
+
const a11yAttr = type === 'label' ? 'aria-labelledby' : 'aria-describedby';
|
|
341
|
+
buttonElement.setAttribute(a11yAttr, tooltipElement.id);
|
|
342
|
+
}
|
|
343
|
+
Object.assign(tooltipElement, restConfig);
|
|
344
|
+
return tooltipElement;
|
|
345
|
+
}
|
|
346
|
+
export async function asyncCreateListItemTooltipIfTextOverflows(tooltip, configId, optionIdIndex, listItemElement, buttonElement, secondaryLabelElement) {
|
|
347
|
+
await frame();
|
|
348
|
+
// Only append the tooltip if the button or secondary label overflow the width of the parent list item.
|
|
349
|
+
if (buttonElement.scrollWidth > listItemElement.clientWidth || secondaryLabelElement.scrollWidth > listItemElement.clientWidth) {
|
|
350
|
+
const tooltipElement = createListItemTooltip(tooltip, configId, optionIdIndex, listItemElement, buttonElement);
|
|
351
|
+
listItemElement.appendChild(tooltipElement);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
306
354
|
export function createCheckboxElement(selected) {
|
|
307
355
|
const checkboxElement = document.createElement('forge-icon');
|
|
308
356
|
checkboxElement.setAttribute(LIST_DROPDOWN_CONSTANTS.attributes.CHECKBOX_ELEMENT, '');
|
|
@@ -35,6 +35,7 @@ export interface IMenuAdapter extends IBaseAdapter {
|
|
|
35
35
|
createChildMenu(index: number, parentValue: any, openCb: (index: number) => void, closeCb: (index: number) => void, selectCb: (data: IMenuSelectEventData) => void): IMenuComponent;
|
|
36
36
|
closeOtherChildMenus(excludeIndex?: number): void;
|
|
37
37
|
setSelectedValues(values: any[]): void;
|
|
38
|
+
resolvePopupTargetById(id: string | null): HTMLElement | null;
|
|
38
39
|
}
|
|
39
40
|
export declare class MenuAdapter extends BaseAdapter<IMenuComponent> implements IMenuAdapter {
|
|
40
41
|
private _targetElement;
|
|
@@ -70,4 +71,5 @@ export declare class MenuAdapter extends BaseAdapter<IMenuComponent> implements
|
|
|
70
71
|
private _getOpenChildMenu;
|
|
71
72
|
private _getOwnList;
|
|
72
73
|
private _getListItems;
|
|
74
|
+
resolvePopupTargetById(id: string | null): HTMLElement | null;
|
|
73
75
|
}
|
package/esm/menu/menu-adapter.js
CHANGED
|
@@ -40,20 +40,16 @@ export class MenuAdapter extends BaseAdapter {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
addTargetListener(event, callback, bubbles = false) {
|
|
43
|
-
|
|
44
|
-
this._targetElement.addEventListener(event, callback, bubbles);
|
|
45
|
-
}
|
|
43
|
+
this._targetElement?.addEventListener(event, callback, bubbles);
|
|
46
44
|
}
|
|
47
45
|
removeTargetListener(event, callback) {
|
|
48
|
-
|
|
49
|
-
this._targetElement.removeEventListener(event, callback);
|
|
50
|
-
}
|
|
46
|
+
this._targetElement?.removeEventListener(event, callback);
|
|
51
47
|
}
|
|
52
48
|
attachMenu(config) {
|
|
53
|
-
if (this._listDropdown || !this._targetElement) {
|
|
49
|
+
if (this._listDropdown || !this._targetElement || !config.referenceElement) {
|
|
54
50
|
return;
|
|
55
51
|
}
|
|
56
|
-
this._listDropdown = new ListDropdown(
|
|
52
|
+
this._listDropdown = new ListDropdown(config.referenceElement, config);
|
|
57
53
|
this._listDropdown.open();
|
|
58
54
|
this._targetElement.setAttribute('aria-expanded', 'true');
|
|
59
55
|
this._targetElement.setAttribute('aria-controls', `list-dropdown-popup-${config.id}`);
|
|
@@ -201,4 +197,12 @@ export class MenuAdapter extends BaseAdapter {
|
|
|
201
197
|
}
|
|
202
198
|
return [];
|
|
203
199
|
}
|
|
200
|
+
resolvePopupTargetById(id) {
|
|
201
|
+
if (!id) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
const root = this._component.getRootNode();
|
|
205
|
+
const contextDocument = root instanceof Document || root instanceof ShadowRoot ? root : document;
|
|
206
|
+
return contextDocument.getElementById(id);
|
|
207
|
+
}
|
|
204
208
|
}
|
|
@@ -9,7 +9,7 @@ const classes = {
|
|
|
9
9
|
POPUP: 'forge-menu__popup'
|
|
10
10
|
};
|
|
11
11
|
const selectors = {
|
|
12
|
-
TOGGLE: `.${elementName}__toggle,[${elementName}-toggle],forge-button,forge-icon-button,forge-fab,button,[type=button],[role=button],a,forge-list-item,[tabindex]:not([tabindex^="-"])`,
|
|
12
|
+
TOGGLE: `.${elementName}__toggle,[${elementName}-toggle],forge-button,forge-icon-button,forge-fab,button,[type=button],[role=button],a,forge-list-item > button,[tabindex]:not([tabindex^="-"])`,
|
|
13
13
|
MENU_LIST: 'forge-list'
|
|
14
14
|
};
|
|
15
15
|
const attributes = {
|
|
@@ -25,7 +25,8 @@ const attributes = {
|
|
|
25
25
|
POPUP_CLASSES: 'popup-classes',
|
|
26
26
|
OPTION_LIMIT: 'option-limit',
|
|
27
27
|
OBSERVE_SCROLL: 'observe-scroll',
|
|
28
|
-
OBSERVE_SCROLL_THRESHOLD: 'observe-scroll-threshold'
|
|
28
|
+
OBSERVE_SCROLL_THRESHOLD: 'observe-scroll-threshold',
|
|
29
|
+
POPUP_TARGET: 'popup-target'
|
|
29
30
|
};
|
|
30
31
|
const events = {
|
|
31
32
|
SELECT: `${elementName}-select`,
|
package/esm/menu/menu-core.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export interface IMenuCore {
|
|
|
26
26
|
mode: MenuMode;
|
|
27
27
|
popupOffset: IOverlayOffset;
|
|
28
28
|
optionBuilder: MenuOptionBuilder | undefined;
|
|
29
|
+
popupTarget: string | null;
|
|
29
30
|
activateFirstOption(): void;
|
|
30
31
|
}
|
|
31
32
|
export declare class MenuCore extends CascadingListDropdownAwareCore<IMenuOption | IMenuOptionGroup> implements IMenuCore {
|
|
@@ -40,6 +41,7 @@ export declare class MenuCore extends CascadingListDropdownAwareCore<IMenuOption
|
|
|
40
41
|
private _mode;
|
|
41
42
|
private _popupOffset;
|
|
42
43
|
private _optionBuilder;
|
|
44
|
+
private _popupTarget;
|
|
43
45
|
private _identifier;
|
|
44
46
|
private _clickListener;
|
|
45
47
|
private _blurListener;
|
|
@@ -82,6 +84,7 @@ export declare class MenuCore extends CascadingListDropdownAwareCore<IMenuOption
|
|
|
82
84
|
protected _setCascadeTargetInactive(): void;
|
|
83
85
|
protected _isOwnElement(element: Element): boolean;
|
|
84
86
|
private _createCascadingElement;
|
|
87
|
+
private _tryResolvePopupTarget;
|
|
85
88
|
private _mapIconToLeadingIcon;
|
|
86
89
|
get open(): boolean;
|
|
87
90
|
set open(value: boolean);
|
|
@@ -106,6 +109,8 @@ export declare class MenuCore extends CascadingListDropdownAwareCore<IMenuOption
|
|
|
106
109
|
set mode(value: MenuMode);
|
|
107
110
|
get popupOffset(): IOverlayOffset;
|
|
108
111
|
set popupOffset(value: IOverlayOffset);
|
|
112
|
+
get popupTarget(): string | null;
|
|
113
|
+
set popupTarget(value: string | null);
|
|
109
114
|
get optionBuilder(): MenuOptionBuilder | undefined;
|
|
110
115
|
set optionBuilder(cb: MenuOptionBuilder | undefined);
|
|
111
116
|
get popupElement(): HTMLElement | null;
|
package/esm/menu/menu-core.js
CHANGED
|
@@ -21,6 +21,7 @@ export class MenuCore extends CascadingListDropdownAwareCore {
|
|
|
21
21
|
this._iconClass = ICON_CLASS_NAME;
|
|
22
22
|
this._persistSelection = false;
|
|
23
23
|
this._mode = 'click';
|
|
24
|
+
this._popupTarget = null;
|
|
24
25
|
this._identifier = randomChars();
|
|
25
26
|
this._clickListener = evt => this._onTargetClick(evt);
|
|
26
27
|
this._blurListener = evt => this._onTargetBlur(evt);
|
|
@@ -218,9 +219,22 @@ export class MenuCore extends CascadingListDropdownAwareCore {
|
|
|
218
219
|
}
|
|
219
220
|
this._mapIconToLeadingIcon();
|
|
220
221
|
const selectedValues = this._persistSelection ? this._getSelectedValues() : [];
|
|
222
|
+
let referenceElement = this._adapter.targetElement;
|
|
223
|
+
if (this._popupTarget) {
|
|
224
|
+
const popupTargetElement = this._adapter.resolvePopupTargetById(this._popupTarget);
|
|
225
|
+
if (popupTargetElement) {
|
|
226
|
+
referenceElement = popupTargetElement;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
const resolvedTarget = this._tryResolvePopupTarget();
|
|
231
|
+
if (resolvedTarget) {
|
|
232
|
+
referenceElement = resolvedTarget;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
221
235
|
const config = {
|
|
222
236
|
id: this._identifier,
|
|
223
|
-
referenceElement
|
|
237
|
+
referenceElement,
|
|
224
238
|
type: ListDropdownType.Menu,
|
|
225
239
|
options: this._options,
|
|
226
240
|
selectedValues,
|
|
@@ -246,7 +260,8 @@ export class MenuCore extends CascadingListDropdownAwareCore {
|
|
|
246
260
|
activeChangeCallback: this._activeChangeListener,
|
|
247
261
|
selectCallback: this._selectListener,
|
|
248
262
|
popupOffset: this._popupOffset,
|
|
249
|
-
cascadingElementFactory: params => this._createCascadingElement(params)
|
|
263
|
+
cascadingElementFactory: params => this._createCascadingElement(params),
|
|
264
|
+
anchorAccessibility: 'none'
|
|
250
265
|
};
|
|
251
266
|
this._adapter.setHostAttribute(MENU_CONSTANTS.attributes.OPEN, '');
|
|
252
267
|
this._adapter.attachMenu(config);
|
|
@@ -391,6 +406,15 @@ export class MenuCore extends CascadingListDropdownAwareCore {
|
|
|
391
406
|
menu.iconClass = this._iconClass;
|
|
392
407
|
return menu;
|
|
393
408
|
}
|
|
409
|
+
_tryResolvePopupTarget() {
|
|
410
|
+
if (this._popupTarget) {
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
// Automatically detect forge-list-item > button case and set popup target if not explicitly set
|
|
414
|
+
if (this._adapter.targetElement?.matches('button')) {
|
|
415
|
+
return this._adapter.targetElement.closest('forge-list-item') ?? undefined;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
394
418
|
_mapIconToLeadingIcon() {
|
|
395
419
|
// For backwards compatibility with old API, map the old "icon" property to the new "leadingIcon" property (if exists)
|
|
396
420
|
this._flatOptions.filter(o => o.icon).forEach(o => (o.leadingIcon = o.icon));
|
|
@@ -516,6 +540,21 @@ export class MenuCore extends CascadingListDropdownAwareCore {
|
|
|
516
540
|
set popupOffset(value) {
|
|
517
541
|
this._popupOffset = value;
|
|
518
542
|
}
|
|
543
|
+
get popupTarget() {
|
|
544
|
+
return this._popupTarget ?? null;
|
|
545
|
+
}
|
|
546
|
+
set popupTarget(value) {
|
|
547
|
+
value = value ?? null;
|
|
548
|
+
if (this._popupTarget !== value) {
|
|
549
|
+
this._popupTarget = value;
|
|
550
|
+
if (this._popupTarget) {
|
|
551
|
+
this._adapter.setHostAttribute(MENU_CONSTANTS.attributes.POPUP_TARGET, this._popupTarget);
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
this._adapter.removeHostAttribute(MENU_CONSTANTS.attributes.POPUP_TARGET);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
519
558
|
get optionBuilder() {
|
|
520
559
|
return this._optionBuilder;
|
|
521
560
|
}
|
package/esm/menu/menu.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export interface IMenuComponent extends IListDropdownAware {
|
|
|
21
21
|
popupOffset: IOverlayOffset;
|
|
22
22
|
optionBuilder: MenuOptionBuilder | undefined;
|
|
23
23
|
popupElement: HTMLElement | undefined;
|
|
24
|
+
popupTarget: string | null;
|
|
24
25
|
propagateKeyEvent(evt: KeyboardEvent): void;
|
|
25
26
|
activateFirstOption(): void;
|
|
26
27
|
}
|
|
@@ -38,8 +39,15 @@ declare global {
|
|
|
38
39
|
/**
|
|
39
40
|
* @tag forge-menu
|
|
40
41
|
*
|
|
42
|
+
* @summary Menus display a list of options or actions that users can select from a dropdown. Menus wrap button or list item elements to provide the trigger for displaying the menu options.
|
|
43
|
+
*
|
|
41
44
|
* @dependency forge-popover
|
|
42
45
|
* @dependency forge-list
|
|
46
|
+
*
|
|
47
|
+
* @event {CustomEvent<IMenuSelectEventData>} forge-menu-select - Dispatches when a menu option is selected.
|
|
48
|
+
* @event {CustomEvent<void>} forge-menu-open - Dispatches when the menu is opened.
|
|
49
|
+
* @event {CustomEvent<void>} forge-menu-close - Dispatches when the menu is closed.
|
|
50
|
+
* @event {CustomEvent<IMenuActiveChangeEventData>} forge-menu-active-change - Dispatches when the active menu option changes.
|
|
43
51
|
*/
|
|
44
52
|
export declare class MenuComponent extends ListDropdownAware implements IMenuComponent {
|
|
45
53
|
static get observedAttributes(): string[];
|
|
@@ -117,6 +125,15 @@ export declare class MenuComponent extends ListDropdownAware implements IMenuCom
|
|
|
117
125
|
* @readonly
|
|
118
126
|
*/
|
|
119
127
|
popupElement: HTMLElement | undefined;
|
|
128
|
+
/**
|
|
129
|
+
* Gets/sets the ID of the element to use as the popup anchor for positioning.
|
|
130
|
+
* When null or empty, the target element (button) is used for both interaction and positioning.
|
|
131
|
+
* This is useful for cases like forge-list-item > button where the menu should be
|
|
132
|
+
* attached to the button for listeners but positioned relative to the list item.
|
|
133
|
+
* @default null
|
|
134
|
+
* @attribute popup-target
|
|
135
|
+
*/
|
|
136
|
+
popupTarget: string | null;
|
|
120
137
|
/**
|
|
121
138
|
* Force propagates the key event from another element to this component.
|
|
122
139
|
*/
|
package/esm/menu/menu.js
CHANGED
|
@@ -19,8 +19,15 @@ const styles = ':host{display:inline-flex}:host([hidden]){display:none}';
|
|
|
19
19
|
/**
|
|
20
20
|
* @tag forge-menu
|
|
21
21
|
*
|
|
22
|
+
* @summary Menus display a list of options or actions that users can select from a dropdown. Menus wrap button or list item elements to provide the trigger for displaying the menu options.
|
|
23
|
+
*
|
|
22
24
|
* @dependency forge-popover
|
|
23
25
|
* @dependency forge-list
|
|
26
|
+
*
|
|
27
|
+
* @event {CustomEvent<IMenuSelectEventData>} forge-menu-select - Dispatches when a menu option is selected.
|
|
28
|
+
* @event {CustomEvent<void>} forge-menu-open - Dispatches when the menu is opened.
|
|
29
|
+
* @event {CustomEvent<void>} forge-menu-close - Dispatches when the menu is closed.
|
|
30
|
+
* @event {CustomEvent<IMenuActiveChangeEventData>} forge-menu-active-change - Dispatches when the active menu option changes.
|
|
24
31
|
*/
|
|
25
32
|
let MenuComponent = class MenuComponent extends ListDropdownAware {
|
|
26
33
|
static get observedAttributes() {
|
|
@@ -38,7 +45,8 @@ let MenuComponent = class MenuComponent extends ListDropdownAware {
|
|
|
38
45
|
MENU_CONSTANTS.attributes.POPUP_CLASSES,
|
|
39
46
|
MENU_CONSTANTS.attributes.OPTION_LIMIT,
|
|
40
47
|
MENU_CONSTANTS.attributes.OBSERVE_SCROLL,
|
|
41
|
-
MENU_CONSTANTS.attributes.OBSERVE_SCROLL_THRESHOLD
|
|
48
|
+
MENU_CONSTANTS.attributes.OBSERVE_SCROLL_THRESHOLD,
|
|
49
|
+
MENU_CONSTANTS.attributes.POPUP_TARGET
|
|
42
50
|
];
|
|
43
51
|
}
|
|
44
52
|
constructor() {
|
|
@@ -82,6 +90,9 @@ let MenuComponent = class MenuComponent extends ListDropdownAware {
|
|
|
82
90
|
case MENU_CONSTANTS.attributes.MODE:
|
|
83
91
|
this.mode = newValue;
|
|
84
92
|
break;
|
|
93
|
+
case MENU_CONSTANTS.attributes.POPUP_TARGET:
|
|
94
|
+
this._core.popupTarget = isDefined(newValue) ? newValue : null;
|
|
95
|
+
break;
|
|
85
96
|
}
|
|
86
97
|
}
|
|
87
98
|
disconnectedCallback() {
|
|
@@ -139,6 +150,9 @@ __decorate([
|
|
|
139
150
|
__decorate([
|
|
140
151
|
coreProperty({ set: false })
|
|
141
152
|
], MenuComponent.prototype, "popupElement", void 0);
|
|
153
|
+
__decorate([
|
|
154
|
+
coreProperty()
|
|
155
|
+
], MenuComponent.prototype, "popupTarget", void 0);
|
|
142
156
|
MenuComponent = __decorate([
|
|
143
157
|
customElement({
|
|
144
158
|
name: MENU_CONSTANTS.elementName,
|
|
@@ -18,7 +18,8 @@ declare global {
|
|
|
18
18
|
/**
|
|
19
19
|
* @tag forge-open-icon
|
|
20
20
|
*
|
|
21
|
-
* @summary Open icons are used to indicate whether a section is open or closed.
|
|
21
|
+
* @summary Open icons are icons used to indicate whether a section is open or closed. They provide an animated transition between the two states to enhance the user experience.
|
|
22
|
+
|
|
22
23
|
*
|
|
23
24
|
* @property {boolean} [open=false] - Whether the icon is open or closed.
|
|
24
25
|
* @property {OpenIconOrientation} [orientation=vertical] - The orientation of the rotation.
|
|
@@ -14,7 +14,8 @@ const styles = ':host{display:inline-flex}:host([hidden]){display:none}.forge-op
|
|
|
14
14
|
/**
|
|
15
15
|
* @tag forge-open-icon
|
|
16
16
|
*
|
|
17
|
-
* @summary Open icons are used to indicate whether a section is open or closed.
|
|
17
|
+
* @summary Open icons are icons used to indicate whether a section is open or closed. They provide an animated transition between the two states to enhance the user experience.
|
|
18
|
+
|
|
18
19
|
*
|
|
19
20
|
* @property {boolean} [open=false] - Whether the icon is open or closed.
|
|
20
21
|
* @property {OpenIconOrientation} [orientation=vertical] - The orientation of the rotation.
|
package/esm/overlay/overlay.d.ts
CHANGED
|
@@ -21,8 +21,7 @@ declare global {
|
|
|
21
21
|
/**
|
|
22
22
|
* @tag forge-overlay
|
|
23
23
|
*
|
|
24
|
-
* @summary Overlays are used to
|
|
25
|
-
* and positioned around a specified anchor element.
|
|
24
|
+
* @summary Overlays are used to show content in an element that is rendered above all other content on the page, and positioned around a specified anchor element. This is a low-level building block component that does not provide any visual styles, but is used within other components such as popovers, and tooltips.
|
|
26
25
|
*
|
|
27
26
|
* @description
|
|
28
27
|
* An overlay is a low-level building block component that does not provide any visual styles. Its only
|
package/esm/overlay/overlay.js
CHANGED
|
@@ -15,8 +15,7 @@ const styles = ':host{display:contents}:host([hidden]){display:none}.forge-overl
|
|
|
15
15
|
/**
|
|
16
16
|
* @tag forge-overlay
|
|
17
17
|
*
|
|
18
|
-
* @summary Overlays are used to
|
|
19
|
-
* and positioned around a specified anchor element.
|
|
18
|
+
* @summary Overlays are used to show content in an element that is rendered above all other content on the page, and positioned around a specified anchor element. This is a low-level building block component that does not provide any visual styles, but is used within other components such as popovers, and tooltips.
|
|
20
19
|
*
|
|
21
20
|
* @description
|
|
22
21
|
* An overlay is a low-level building block component that does not provide any visual styles. Its only
|
|
@@ -12,9 +12,10 @@ declare global {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
15
|
* @tag forge-page-state
|
|
17
16
|
*
|
|
17
|
+
* @summary Page states display full-height messages for empty states, errors, or other general information. They can be used as full page content, or within smaller containers and will adapt accordingly.
|
|
18
|
+
*
|
|
18
19
|
* @cssproperty --forge-page-state-width - The width of the page state.
|
|
19
20
|
* @cssproperty --forge-page-state-height - The height of the page state.
|
|
20
21
|
* @cssproperty --forge-page-state-spacing - The spacing of the page state.
|
|
@@ -10,9 +10,10 @@ import { PAGE_STATE_CONSTANTS } from './page-state-constants';
|
|
|
10
10
|
const template = '<template><div class=\"forge-page-state\" part=\"root\"><div class=\"graphic\" part=\"graphic-container\"><slot name=\"graphic\"></slot></div><div class=\"title\" part=\"title-container\"><slot name=\"title\"></slot></div><div class=\"message\" part=\"message-container\"><slot name=\"message\"></slot></div><div class=\"actions\" part=\"actions-container\"><slot name=\"action\"></slot></div></div></template>';
|
|
11
11
|
const styles = ':host{--_page-state-width:var(--forge-page-state-width, 576px);--_page-state-height:var(--forge-page-state-height, auto);--_page-state-spacing:var(--forge-page-state-spacing, var(--forge-spacing-xxxlarge, 56px));--_page-state-mobile-width:var(--forge-page-state-mobile-width, 70%);--_page-state-graphic-height:var(--forge-page-state-graphic-height, 296px);--_page-state-graphic-spacing:var(--forge-page-state-graphic-spacing, var(--forge-spacing-xxxlarge, 56px));--_page-state-mobile-graphic-height:var(--forge-page-state-mobile-graphic-height, auto);--_page-state-title-color:var(--forge-page-state-title-color, var(--forge-theme-text-medium, rgba(0, 0, 0, 0.6)));--_page-state-title-spacing:var(--forge-page-state-title-spacing, var(--forge-spacing-xxxlarge, 56px));--_page-state-title-spacing-mobile:var(--forge-page-state-title-spacing-mobile, var(--forge-spacing-large, 24px));--_page-state-message-color:var(--forge-page-state-message-color, var(--forge-theme-text-high, rgba(0, 0, 0, 0.87)));--_page-state-message-spacing:var(--forge-page-state-message-spacing, var(--forge-spacing-xxxlarge, 56px));--_page-state-message-spacing-mobile:var(--forge-page-state-message-spacing-mobile, var(--forge-spacing-large, 24px));--_page-state-actions-spacing:var(--forge-page-state-actions-spacing, 16px)}:host{display:flex;justify-content:center;align-items:center;width:100%;container-type:inline-size}:host([hidden]){display:none}.forge-page-state{width:var(--_page-state-width);margin-block:var(--_page-state-spacing);text-align:center}.forge-page-state .graphic{display:flex;justify-content:center;align-items:center;height:var(--_page-state-graphic-height);width:100%;margin-block-end:var(--_page-state-graphic-spacing)}.forge-page-state .graphic ::slotted([slot=graphic]){height:100%;width:100%}.forge-page-state .title{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--forge-typography-heading8-font-family, var(--forge-typography-font-family, \"Roboto\", sans-serif));font-size:var(--forge-typography-heading8-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-heading8-font-size-scale, 2.25)));font-weight:var(--forge-typography-heading8-font-weight,500);line-height:var(--forge-typography-heading8-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-heading8-line-height-scale, 2.625)));letter-spacing:var(--forge-typography-heading8-letter-spacing, -.0027777778em);text-transform:var(--forge-typography-heading8-text-transform,inherit);text-decoration:var(--forge-typography-heading8-text-decoration,inherit);--_page-state-title-spacing:var(--_page-state-title-spacing-mobile);color:var(--_page-state-title-color);margin-block:var(--_page-state-title-spacing)}.forge-page-state .message{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--forge-typography-body4-font-family, var(--forge-typography-font-family, \"Roboto\", sans-serif));font-size:var(--forge-typography-body4-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-font-size-scale, 1.25)));font-weight:var(--forge-typography-body4-font-weight,400);line-height:var(--forge-typography-body4-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-line-height-scale, 1.75)));letter-spacing:var(--forge-typography-body4-letter-spacing, .005em);text-transform:var(--forge-typography-body4-text-transform,inherit);text-decoration:var(--forge-typography-body4-text-decoration,inherit);--_page-state-message-spacing:var(--_page-state-message-spacing-mobile);color:var(--_page-state-message-color);margin-block-end:var(--_page-state-message-spacing)}.forge-page-state .actions{display:grid;justify-content:center;grid-auto-flow:column;gap:var(--_page-state-actions-spacing)}@container (max-width:599px){.forge-page-state{--_page-state-width:var(--_page-state-mobile-width)}.forge-page-state .graphic{--_page-state-graphic-height:var(--_page-state-mobile-graphic-height);--_page-state-graphic-spacing:var(--forge-page-state-graphic-spacing, 0)}.forge-page-state .title{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--forge-typography-heading5-font-family, var(--forge-typography-font-family, \"Roboto\", sans-serif));font-size:var(--forge-typography-heading5-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-heading5-font-size-scale, 1.5)));font-weight:var(--forge-typography-heading5-font-weight,500);line-height:var(--forge-typography-heading5-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-heading5-line-height-scale, 1.75)));letter-spacing:var(--forge-typography-heading5-letter-spacing, 0);text-transform:var(--forge-typography-heading5-text-transform,inherit);text-decoration:var(--forge-typography-heading5-text-decoration,inherit)}.forge-page-state .message{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:var(--forge-typography-body2-font-family, var(--forge-typography-font-family, \"Roboto\", sans-serif));font-size:var(--forge-typography-body2-font-size, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-font-size-scale, 1)));font-weight:var(--forge-typography-body2-font-weight,400);line-height:var(--forge-typography-body2-line-height, calc(var(--forge-typography-font-size, 1rem) * var(--forge-typography-body-line-height-scale, 1.375)));letter-spacing:var(--forge-typography-body2-letter-spacing, .015625em);text-transform:var(--forge-typography-body2-text-transform,inherit);text-decoration:var(--forge-typography-body2-text-decoration,inherit)}.forge-page-state .actions{grid-auto-flow:row}}';
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
13
|
* @tag forge-page-state
|
|
15
14
|
*
|
|
15
|
+
* @summary Page states display full-height messages for empty states, errors, or other general information. They can be used as full page content, or within smaller containers and will adapt accordingly.
|
|
16
|
+
*
|
|
16
17
|
* @cssproperty --forge-page-state-width - The width of the page state.
|
|
17
18
|
* @cssproperty --forge-page-state-height - The height of the page state.
|
|
18
19
|
* @cssproperty --forge-page-state-spacing - The spacing of the page state.
|