@odx/foundation 1.0.0-beta.81 → 1.0.0-beta.83

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.
@@ -1,6 +1,7 @@
1
1
  import { OdxIconName } from '@odx/icons';
2
2
  import { PropertyValues, TemplateResult } from 'lit';
3
3
  import { OdxButton } from '../button/button.js';
4
+ import { OdxTooltip } from '../tooltip/tooltip.js';
4
5
  declare global {
5
6
  interface HTMLElementTagNameMap {
6
7
  'odx-action-button': OdxActionButton;
@@ -8,6 +9,7 @@ declare global {
8
9
  }
9
10
  export declare class OdxActionButton extends OdxButton {
10
11
  #private;
12
+ protected tooltip?: OdxTooltip;
11
13
  /** @internal */
12
14
  protected isStatusMessageShown: boolean;
13
15
  done: boolean;
@@ -17,7 +19,6 @@ export declare class OdxActionButton extends OdxButton {
17
19
  statusTimeout: number;
18
20
  statusMessageTimeout: number;
19
21
  replaceContent: boolean;
20
- connectedCallback(): void;
21
22
  protected firstUpdated(props: PropertyValues<this>): void;
22
23
  protected render(): TemplateResult;
23
24
  protected renderContent(): TemplateResult;
@@ -18,7 +18,7 @@ export declare class OdxDropdown extends PopoverHost {
18
18
  get options(): PopoverPlacementOptions;
19
19
  connectedCallback(): void;
20
20
  mountPopover(referenceElement: HTMLElement | null): void;
21
- unmountPopover(referenceElement: HTMLElement): void;
21
+ unmountPopover(referenceElement: HTMLElement | null): void;
22
22
  protected render(): TemplateResult;
23
23
  protected willUpdate(props: PropertyValues<this>): void;
24
24
  }
@@ -1,11 +1,11 @@
1
1
  import { CanBeDisabled, CustomElement, Placement, PopoverPlacementOptions } from '../../lib/main.js';
2
+ import { PropertyValues } from 'lit';
2
3
  import { OdxPopover } from './popover.js';
3
4
  declare const PopoverHost_base: import('../../lib/main.js').Constructor<CanBeDisabled> & typeof CustomElement;
4
- export declare class PopoverHost extends PopoverHost_base {
5
+ export declare abstract class PopoverHost extends PopoverHost_base {
5
6
  #private;
6
7
  static readonly styles: import('lit').CSSResult;
7
- private isOpen;
8
- popoverElement: OdxPopover;
8
+ protected popoverElement: OdxPopover;
9
9
  referenceElement: HTMLElement | null;
10
10
  anchor: string;
11
11
  placement: Placement;
@@ -14,18 +14,21 @@ export declare class PopoverHost extends PopoverHost_base {
14
14
  constructor();
15
15
  connectedCallback(): void;
16
16
  disconnectedCallback(): void;
17
+ hasMountedPopover(element: HTMLElement): boolean;
17
18
  mountPopover(referenceElement: HTMLElement | null): void;
18
- unmountPopover(_referenceElement: HTMLElement): void;
19
+ unmountPopover(_referenceElement: HTMLElement | null): void;
19
20
  isPopoverOpen(): boolean;
20
21
  showPopover(): Promise<void>;
21
22
  hidePopover(): void;
22
23
  togglePopover(state?: boolean): boolean;
23
24
  canPopoverShow?(): boolean;
24
- onBeforePopoverShow?(): void;
25
- onPopoverShow?(): void;
26
- onBeforePopoverHide?(): void;
27
- onPopoverHide?(): void;
25
+ onBeforePopoverShow?(): Promise<void> | void;
26
+ onPopoverShow?(): Promise<void> | void;
28
27
  canPopoverHide?(): boolean;
28
+ onBeforePopoverHide?(): Promise<void> | void;
29
+ onPopoverHide?(): Promise<void> | void;
30
+ updateReferenceElementFromEvent(event: Event): void;
31
+ protected willUpdate(props: PropertyValues<this>): void;
29
32
  }
30
33
  export {};
31
34
  //# sourceMappingURL=popover-host.d.ts.map
@@ -4,6 +4,7 @@ export declare class PopoverObserver {
4
4
  readonly host: PopoverHost;
5
5
  readonly root: ShadowRoot | Document;
6
6
  constructor(host: PopoverHost);
7
+ hasMountedPopover(element: HTMLElement): boolean;
7
8
  observe(): void;
8
9
  disconnect(): void;
9
10
  updateReferenceElements(): void;
@@ -10,9 +10,11 @@ declare global {
10
10
  export declare class OdxSelect extends ListboxFormControl<OptionControl> {
11
11
  #private;
12
12
  protected options: OdxOption[];
13
+ protected readonly trigger: HTMLElement;
13
14
  protected readonly dropdown: OdxDropdown;
14
15
  maxVisibleSelectedOptions: number;
15
16
  constructor();
17
+ firstUpdated(): void;
16
18
  isDropdownOpen(): boolean;
17
19
  showDropdown(): void;
18
20
  hideDropdown(): void;
@@ -1,6 +1,6 @@
1
1
  import { _ as __decorateClass } from './_virtual_class-decorator-runtime.js';
2
- import { CustomElement, ExpandableItemManager, customElement, CanBeExpanded, InteractiveElement, getUniqueId, toAriaBooleanAttribute, Size, Variant, optionalAttr, InteractiveLink, getElementFromEvent, Shape, CanBeDisabled, optionalSlot, CheckboxFormControl, CheckboxGroupFormControl, SharedResizeObserver, Placement, waitForAnimations, PopoverPlacementOptions, computePopoverPlacement, findClosestDocument, getKeyInfo, FormControl, ActiveDescendantsController, getAssignedElement, parseDate, forwardEvent, OptionControl, toPx, RadioGroupFormControl, ListboxFormControl, IsDraggable, NumberFormControl, IS_DRAG_ACTIVE_ATTRIBUTE, DragController } from '@odx/foundation';
3
- import { queryAssignedElements, property, state, queryAll, query } from 'lit/decorators.js';
2
+ import { CustomElement, ExpandableItemManager, customElement, CanBeExpanded, InteractiveElement, getUniqueId, toAriaBooleanAttribute, Size, Variant, optionalAttr, InteractiveLink, getElementFromEvent, Shape, CanBeDisabled, optionalSlot, CheckboxFormControl, CheckboxGroupFormControl, SharedResizeObserver, findClosestDocument, Placement, waitForAnimations, PopoverPlacementOptions, computePopoverPlacement, getKeyInfo, FormControl, ActiveDescendantsController, getAssignedElement, parseDate, forwardEvent, OptionControl, toPx, RadioGroupFormControl, ListboxFormControl, IsDraggable, NumberFormControl, IS_DRAG_ACTIVE_ATTRIBUTE, DragController } from '@odx/foundation';
3
+ import { queryAssignedElements, property, query, state, queryAll } from 'lit/decorators.js';
4
4
  import { html, isServer, unsafeCSS, css, nothing } from 'lit';
5
5
  import { when } from 'lit/directives/when.js';
6
6
  import { p as pick, e, a as autoUpdate, t as throttle, R as RovingTabindexController, r as round, g as debounce, n, i as c, j as e$1 } from './vendor.js';
@@ -187,10 +187,6 @@ const _OdxActionButton = class _OdxActionButton extends OdxButton {
187
187
  }
188
188
  /** @internal */
189
189
  #statusTimeout;
190
- connectedCallback() {
191
- super.connectedCallback();
192
- this.id ||= getUniqueId(this.localName);
193
- }
194
190
  firstUpdated(props) {
195
191
  super.firstUpdated(props);
196
192
  this.nativeElement.addEventListener("click", this.#handleClick);
@@ -233,6 +229,7 @@ const _OdxActionButton = class _OdxActionButton extends OdxButton {
233
229
  #handleDoneChange() {
234
230
  const timeoutDuration = Math.max(0, this.statusTimeout);
235
231
  this.isStatusMessageShown = true;
232
+ this.tooltip?.mountPopover(this.nativeElement);
236
233
  if (this.statusTimeout <= 0) return;
237
234
  clearTimeout(this.#statusTimeout);
238
235
  this.#statusTimeout = window.setTimeout(() => {
@@ -242,6 +239,9 @@ const _OdxActionButton = class _OdxActionButton extends OdxButton {
242
239
  }
243
240
  #handleClick;
244
241
  };
242
+ __decorateClass([
243
+ query("odx-tooltip")
244
+ ], _OdxActionButton.prototype, "tooltip", 2);
245
245
  __decorateClass([
246
246
  state()
247
247
  ], _OdxActionButton.prototype, "isStatusMessageShown", 2);
@@ -936,25 +936,64 @@ let OdxCircularProgressBar = _OdxCircularProgressBar;
936
936
 
937
937
  const styles$Z = "@layer base{:host{--max-block-size: 100%;--max-inline-size: 100%;--_popover-color-background: var(--odx-color-background-level-2);--_popover-color-foreground: var(--odx-color-foreground-rest);--_popover-min-block-size: inherit;--_popover-max-block-size: 100%;--_popover-min-inline-size: inherit;--_popover-max-inline-size: 100%;--_popover-transition: var(--odx-popover-transition, var(--odx-motion-duration-default));--_popover-offset: var(--odx-size-50);--_popover-shadow: var(--odx-popover-shadow, var(--odx-shadow-level-1));--_popover-outer-padding: var(--odx-size-75);--_popover-arrow-size: var(--odx-size-50);--_popover-arrow-offset: calc(var(--_popover-offset) - var(--_popover-arrow-size) / 2);--_max-block-size: min(var(--_popover-max-block-size), var(--max-block-size));--_max-inline-size: min(var(--_popover-max-inline-size), var(--max-inline-size));top:var(--_popover-position-y);left:var(--_popover-position-x);transform:translate3d(var(--_popover-transition-offset-x),var(--_popover-transition-offset-y),0);transition:opacity var(--_popover-transition),transform var(--_popover-transition) allow-discrete,overlay var(--_popover-transition) allow-discrete,display var(--_popover-transition) allow-discrete;opacity:0;margin:0;background-color:transparent;max-block-size:var(--_max-block-size);max-inline-size:var(--_max-inline-size)}:host(:not(:popover-open)){display:none}:host(:popover-open){display:flex;transform:translate(0);opacity:1;@starting-style{transform:translate(var(--_popover-transition-offset-x),var(--_popover-transition-offset-y));opacity:0}}odx-popover::part(arrow){transform:rotate(45deg)}}@layer state{:host([popover-placement^=\"top\"]){--_popover-transition-offset-x: 0;--_popover-transition-offset-y: calc(-1 * var(--_popover-offset));padding-block:var(--_popover-outer-padding) var(--_popover-offset);max-block-size:calc(var(--_max-block-size) - var(--_popover-outer-padding));odx-popover::part(arrow){bottom:var(--_popover-arrow-offset)}}:host([popover-placement^=\"right\"]){--_popover-transition-offset-x: var(--_popover-offset);--_popover-transition-offset-y: 0;padding-inline:var(--_popover-offset) var(--_popover-outer-padding);max-inline-size:calc(var(--_max-inline-size) - var(--_popover-outer-padding));odx-popover::part(arrow){left:var(--_popover-arrow-offset)}}:host([popover-placement^=\"bottom\"]){--_popover-transition-offset-x: 0;--_popover-transition-offset-y: var(--_popover-offset);--_popover-arrow-offset-y: calc(var(--_popover-offset) - 6px);padding-block:var(--_popover-offset) var(--_popover-outer-padding);max-block-size:calc(var(--_max-block-size) - var(--_popover-outer-padding));odx-popover::part(arrow){top:var(--_popover-arrow-offset)}}:host([popover-placement^=\"left\"]){--_popover-transition-offset-x: calc(-1 * var(--_popover-offset));--_popover-transition-offset-y: 0;--_popover-arrow-offset-x: calc(var(--_popover-offset) - var(--_arrow-size) / 2);--_popover-arrow-offset-y: 0;padding-inline:var(--_popover-offset) var(--_popover-outer-padding);max-inline-size:calc(var(--_max-inline-size) - var(--_popover-outer-padding));odx-popover::part(arrow){right:var(--_popover-offset)}}}";
938
938
 
939
+ const popoverTargetAttribute = "odx-popovertarget";
940
+ class PopoverObserver {
941
+ #referenceElements = /* @__PURE__ */ new WeakMap();
942
+ #mutationObserver;
943
+ constructor(host) {
944
+ this.host = host;
945
+ this.root = findClosestDocument(host) ?? document;
946
+ this.#mutationObserver = new MutationObserver(async (mutations) => {
947
+ if (mutations.length === 0) return;
948
+ await 0;
949
+ this.updateReferenceElements();
950
+ });
951
+ }
952
+ hasMountedPopover(element) {
953
+ return this.#referenceElements.has(element);
954
+ }
955
+ observe() {
956
+ this.#mutationObserver?.observe(this.root, { attributes: true, subtree: true, childList: true, attributeFilter: [popoverTargetAttribute] });
957
+ this.updateReferenceElements();
958
+ }
959
+ disconnect() {
960
+ this.#mutationObserver?.disconnect();
961
+ }
962
+ updateReferenceElements() {
963
+ for (const element of Array.from(this.root.querySelectorAll(`[${popoverTargetAttribute}]`))) {
964
+ if (this.#referenceElements.has(element)) continue;
965
+ const popoverId = element.getAttribute(popoverTargetAttribute);
966
+ if (popoverId !== this.host.id) continue;
967
+ this.#referenceElements.set(element, popoverId);
968
+ this.host.mountPopover?.(element);
969
+ }
970
+ }
971
+ }
972
+
939
973
  class PopoverHost extends CanBeDisabled(CustomElement) {
940
974
  constructor() {
941
975
  super();
942
- this.isOpen = false;
976
+ this.#openPopovers = /* @__PURE__ */ new WeakSet();
943
977
  this.referenceElement = null;
944
978
  this.anchor = "";
945
979
  this.placement = Placement.BOTTOM;
946
980
  this.fpsLimit = 60;
947
981
  this.#handleToggle = async (event) => {
948
- if (this.isOpen) {
949
- this.onBeforePopoverShow?.();
982
+ if (this.isPopoverOpen()) {
983
+ await this.onBeforePopoverShow?.();
950
984
  await waitForAnimations(this);
951
- this.onPopoverShow?.();
985
+ await this.onPopoverShow?.();
952
986
  } else {
953
- this.onBeforePopoverHide?.();
987
+ await this.onBeforePopoverHide?.();
954
988
  await waitForAnimations(this);
955
- this.onPopoverHide?.();
989
+ await this.onPopoverHide?.();
990
+ }
991
+ if (!this.referenceElement) return;
992
+ if (event.newState === "open") {
993
+ this.#openPopovers.add(this.referenceElement);
994
+ } else {
995
+ this.#openPopovers.delete(this.referenceElement);
956
996
  }
957
- this.isOpen = event.newState === "open";
958
997
  };
959
998
  if (!isServer) {
960
999
  this.addEventListener("toggle", this.#handleToggle);
@@ -963,6 +1002,7 @@ class PopoverHost extends CanBeDisabled(CustomElement) {
963
1002
  static {
964
1003
  this.styles = unsafeCSS(styles$Z);
965
1004
  }
1005
+ #openPopovers;
966
1006
  #positionUpdater;
967
1007
  #observer;
968
1008
  get options() {
@@ -977,26 +1017,28 @@ class PopoverHost extends CanBeDisabled(CustomElement) {
977
1017
  super.disconnectedCallback();
978
1018
  this.#disconnectObserver();
979
1019
  if (!this.referenceElement) return;
980
- this.unmountPopover(this.referenceElement);
1020
+ this.unmountPopover?.(this.referenceElement);
1021
+ this.hidePopover();
1022
+ }
1023
+ hasMountedPopover(element) {
1024
+ return this.#observer?.hasMountedPopover(element) ?? false;
981
1025
  }
982
1026
  mountPopover(referenceElement) {
983
- if (this.referenceElement && this.referenceElement !== referenceElement) {
984
- this.unmountPopover(this.referenceElement);
985
- }
986
- this.referenceElement = referenceElement ?? null;
1027
+ if (!referenceElement) return;
1028
+ this.referenceElement = referenceElement;
987
1029
  }
988
1030
  unmountPopover(_referenceElement) {
989
- this.hidePopover();
1031
+ this.referenceElement = null;
990
1032
  }
991
1033
  isPopoverOpen() {
992
- return this.isOpen;
1034
+ return !!this.referenceElement && this.#openPopovers.has(this.referenceElement);
993
1035
  }
994
1036
  async showPopover() {
995
- if (!this.referenceElement || this.isOpen || this.disabled || this.canPopoverShow?.() === false) return;
1037
+ if (!this.referenceElement || this.disabled || this.canPopoverShow?.() === false) return;
996
1038
  await 0;
997
1039
  computePopoverPlacement(this.referenceElement, this, this.options);
998
1040
  super.showPopover();
999
- this.isOpen = true;
1041
+ this.#openPopovers.add(this.referenceElement);
1000
1042
  this.#positionUpdater?.();
1001
1043
  this.#positionUpdater = autoUpdate(
1002
1044
  this.referenceElement,
@@ -1005,14 +1047,16 @@ class PopoverHost extends CanBeDisabled(CustomElement) {
1005
1047
  );
1006
1048
  }
1007
1049
  hidePopover() {
1008
- if (!this.isOpen || this.canPopoverHide?.() === false) return;
1050
+ if (!this.isPopoverOpen() || this.canPopoverHide?.() === false) return;
1009
1051
  this.#positionUpdater?.();
1010
1052
  super.hidePopover();
1011
- this.isOpen = false;
1053
+ if (this.referenceElement) {
1054
+ this.#openPopovers.delete(this.referenceElement);
1055
+ }
1012
1056
  this.#positionUpdater = void 0;
1013
1057
  }
1014
- togglePopover(state2) {
1015
- const isOpen = state2 ?? !this.isPopoverOpen();
1058
+ togglePopover(state) {
1059
+ const isOpen = state ?? !this.isPopoverOpen();
1016
1060
  if (isOpen) {
1017
1061
  this.showPopover();
1018
1062
  } else {
@@ -1020,18 +1064,24 @@ class PopoverHost extends CanBeDisabled(CustomElement) {
1020
1064
  }
1021
1065
  return isOpen;
1022
1066
  }
1023
- #findReferenceElement(anchor) {
1024
- return findClosestDocument(this)?.getElementById(anchor) ?? null;
1067
+ updateReferenceElementFromEvent(event) {
1068
+ const referenceElement = getElementFromEvent(event, (element) => this.hasMountedPopover(element));
1069
+ if (!referenceElement) return;
1070
+ this.referenceElement = getElementFromEvent(event, (element) => this.hasMountedPopover(element));
1071
+ }
1072
+ willUpdate(props) {
1073
+ super.willUpdate(props);
1074
+ if (props.has("referenceElement") && this.referenceElement !== props.get("referenceElement")) {
1075
+ const previousReferenceElement = props.get("referenceElement");
1076
+ if (previousReferenceElement) {
1077
+ this.#openPopovers.delete(previousReferenceElement);
1078
+ }
1079
+ }
1025
1080
  }
1026
1081
  #connectObserver() {
1027
1082
  this.#disconnectObserver();
1028
- this.mountPopover(this.#findReferenceElement(this.anchor));
1029
- this.#observer = new MutationObserver(() => {
1030
- const referenceElement = this.anchor ? this.#findReferenceElement(this.anchor) : null;
1031
- if (this.referenceElement === referenceElement) return;
1032
- this.mountPopover(referenceElement);
1033
- });
1034
- this.#observer?.observe(document.documentElement, { subtree: true, attributeFilter: ["id", "anchor"] });
1083
+ this.#observer = new PopoverObserver(this);
1084
+ this.#observer?.observe();
1035
1085
  }
1036
1086
  #disconnectObserver() {
1037
1087
  this.#observer?.disconnect();
@@ -1039,14 +1089,11 @@ class PopoverHost extends CanBeDisabled(CustomElement) {
1039
1089
  }
1040
1090
  #handleToggle;
1041
1091
  }
1042
- __decorateClass([
1043
- state()
1044
- ], PopoverHost.prototype, "isOpen", 2);
1045
1092
  __decorateClass([
1046
1093
  query("odx-popover", true)
1047
1094
  ], PopoverHost.prototype, "popoverElement", 2);
1048
1095
  __decorateClass([
1049
- state()
1096
+ property({ attribute: false })
1050
1097
  ], PopoverHost.prototype, "referenceElement", 2);
1051
1098
  __decorateClass([
1052
1099
  property({ reflect: true, useDefault: true })
@@ -1068,10 +1115,12 @@ const _OdxDropdown = class _OdxDropdown extends PopoverHost {
1068
1115
  this.placement = DropdownPlacement.BOTTOM;
1069
1116
  this.#handleClick = (event) => {
1070
1117
  if (event?.defaultPrevented) return;
1118
+ this.updateReferenceElementFromEvent(event);
1071
1119
  this.togglePopover();
1072
1120
  };
1073
1121
  this.#handleKeyboardEvent = (event) => {
1074
- if (!getKeyInfo(event).enter || event.defaultPrevented) return;
1122
+ const key = getKeyInfo(event);
1123
+ if (!key.enter || event.defaultPrevented) return;
1075
1124
  if (!this.isPopoverOpen()) {
1076
1125
  event.stopImmediatePropagation();
1077
1126
  }
@@ -1092,14 +1141,15 @@ const _OdxDropdown = class _OdxDropdown extends PopoverHost {
1092
1141
  this.id ||= getUniqueId("odx-dropdown");
1093
1142
  }
1094
1143
  mountPopover(referenceElement) {
1095
- super.mountPopover(referenceElement);
1144
+ super.mountPopover?.(referenceElement);
1096
1145
  if (this.disabled || !referenceElement) return;
1097
1146
  this.#updateAriaAttributes(referenceElement, this.id);
1098
1147
  referenceElement.addEventListener("click", this.#handleClick);
1099
1148
  referenceElement.addEventListener("keydown", this.#handleKeyboardEvent);
1100
1149
  }
1101
1150
  unmountPopover(referenceElement) {
1102
- super.unmountPopover(referenceElement);
1151
+ super.unmountPopover?.(referenceElement);
1152
+ if (!referenceElement) return;
1103
1153
  this.#updateAriaAttributes(referenceElement, null);
1104
1154
  referenceElement.removeEventListener("click", this.#handleClick);
1105
1155
  referenceElement.removeEventListener("keydown", this.#handleKeyboardEvent);
@@ -1118,7 +1168,7 @@ const _OdxDropdown = class _OdxDropdown extends PopoverHost {
1118
1168
  }
1119
1169
  if (props.has("disabled")) {
1120
1170
  if (this.disabled) {
1121
- this.referenceElement && this.unmountPopover(this.referenceElement);
1171
+ this.unmountPopover(this.referenceElement);
1122
1172
  } else {
1123
1173
  this.mountPopover(this.referenceElement);
1124
1174
  }
@@ -1240,13 +1290,12 @@ const _OdxAutocomplete = class _OdxAutocomplete extends FormControl {
1240
1290
  if (!this.control) return;
1241
1291
  this.control.addEventListener("blur", this.#handleControlFocusOut);
1242
1292
  this.control.addEventListener("clear", this.#handleControlClear);
1243
- this.control.addEventListener("click", (event) => {
1244
- event.preventDefault();
1245
- });
1293
+ this.control.addEventListener("click", (event) => event.preventDefault());
1246
1294
  this.control.addEventListener("focus", this.#handleControlFocusIn);
1247
1295
  this.control.addEventListener("input", this.#handleControlInput);
1248
1296
  this.control.addEventListener("keydown", this.#handleControlKeyboardEvent);
1249
- this.dropdown.referenceElement = this.control;
1297
+ this.dropdown.popover = "manual";
1298
+ this.dropdown.mountPopover(this.control);
1250
1299
  };
1251
1300
  this.#handleControlFocusIn = () => {
1252
1301
  if (this.dropdown.canPopoverShow?.() === false) return;
@@ -1289,7 +1338,7 @@ const _OdxAutocomplete = class _OdxAutocomplete extends FormControl {
1289
1338
  customElement("odx-autocomplete", styles$W)(_OdxAutocomplete);
1290
1339
  }
1291
1340
  get control() {
1292
- return getAssignedElement(this, { slot: "control" });
1341
+ return getAssignedElement(this.shadowRoot, { slot: "control" });
1293
1342
  }
1294
1343
  get controlValue() {
1295
1344
  return this.control?.value ?? "";
@@ -1304,7 +1353,13 @@ const _OdxAutocomplete = class _OdxAutocomplete extends FormControl {
1304
1353
  render() {
1305
1354
  return html`
1306
1355
  <slot name="control" @slotchange=${this.#handleControlSlotChange}></slot>
1307
- <odx-dropdown part="dropdown" role="listbox" tabindex="-1" ?disabled=${this.disabled} match-reference-width .popover="${"manual"}">
1356
+ <odx-dropdown
1357
+ part="dropdown"
1358
+ role="listbox"
1359
+ tabindex="-1"
1360
+ ?disabled=${this.disabled}
1361
+ match-reference-width
1362
+ >
1308
1363
  <odx-highlight minlength=${this.minQueryLength} selector="odx-option" subtle .root=${this}>
1309
1364
  <odx-stack gap="xs">
1310
1365
  <slot></slot>
@@ -2444,14 +2499,14 @@ class OdxMenu extends PopoverHost {
2444
2499
  this.role ||= "menu";
2445
2500
  }
2446
2501
  mountPopover(referenceElement) {
2447
- super.mountPopover(referenceElement);
2502
+ super.mountPopover?.(referenceElement);
2448
2503
  referenceElement?.addEventListener("click", this.#handleReferenceInteraction);
2449
2504
  referenceElement?.addEventListener("keydown", this.#handleReferenceKeyDown);
2450
2505
  }
2451
2506
  unmountPopover(referenceElement) {
2452
2507
  referenceElement.removeEventListener("keydown", this.#handleReferenceKeyDown);
2453
2508
  referenceElement.removeEventListener("click", this.#handleReferenceInteraction);
2454
- super.unmountPopover(referenceElement);
2509
+ super.unmountPopover?.(referenceElement);
2455
2510
  }
2456
2511
  onBeforePopoverShow() {
2457
2512
  this.#tabindexController.update({ elements: () => this.getItems() });
@@ -2476,7 +2531,8 @@ class OdxMenu extends PopoverHost {
2476
2531
  </odx-popover>
2477
2532
  `;
2478
2533
  }
2479
- #handleReferenceInteraction = () => {
2534
+ #handleReferenceInteraction = (event) => {
2535
+ this.updateReferenceElementFromEvent(event);
2480
2536
  this.togglePopover();
2481
2537
  };
2482
2538
  #handleClick = (event) => {
@@ -2490,16 +2546,10 @@ class OdxMenu extends PopoverHost {
2490
2546
  };
2491
2547
  #handleKeyDown = (event) => {
2492
2548
  const key = getKeyInfo(event);
2493
- if ((key.tab || key.backTab) && this.isPopoverOpen()) {
2494
- event?.preventDefault();
2495
- event.stopPropagation();
2496
- this.hidePopover();
2497
- return;
2498
- }
2499
- if (!(key.enter || key.space)) return;
2500
- const [activeItem] = this.getItems().filter((item) => item.tabIndex === 0);
2501
- if (!activeItem) return;
2502
- activeItem.click();
2549
+ if (!(this.isPopoverOpen() && (key.tab || key.backTab))) return;
2550
+ event?.preventDefault();
2551
+ event.stopPropagation();
2552
+ this.hidePopover();
2503
2553
  };
2504
2554
  #handleReferenceKeyDown = (event) => {
2505
2555
  if (!getKeyInfo(event).down) return;
@@ -3213,6 +3263,10 @@ const _OdxSelect = class _OdxSelect extends ListboxFormControl {
3213
3263
  static {
3214
3264
  customElement("odx-select", styles$o)(_OdxSelect);
3215
3265
  }
3266
+ firstUpdated() {
3267
+ const referenceElement = this.shadowRoot?.querySelector(".base") ?? null;
3268
+ this.dropdown.mountPopover(referenceElement);
3269
+ }
3216
3270
  isDropdownOpen() {
3217
3271
  return this.dropdown.isPopoverOpen();
3218
3272
  }
@@ -3224,7 +3278,7 @@ const _OdxSelect = class _OdxSelect extends ListboxFormControl {
3224
3278
  }
3225
3279
  render() {
3226
3280
  return html`
3227
- <div id="select-trigger" class="base" tabindex="0">
3281
+ <div class="base" tabindex="0">
3228
3282
  <div class="value" odxPreventTextOverflow>
3229
3283
  ${when(
3230
3284
  this.selectedOptions.length,
@@ -3238,7 +3292,7 @@ const _OdxSelect = class _OdxSelect extends ListboxFormControl {
3238
3292
  )}
3239
3293
  <odx-icon class="indicator" name="core::chevron-down"></odx-icon>
3240
3294
  </div>
3241
- <odx-dropdown part="dropdown" anchor="select-trigger" role="listbox" tabindex="-1" ?disabled=${this.disabled || this.readonly} match-reference-width>
3295
+ <odx-dropdown part="dropdown" role="listbox" tabindex="-1" ?disabled=${this.disabled || this.readonly} match-reference-width .referenceElement=${this.trigger}>
3242
3296
  <slot @slotchange=${this.#handleSlotChange}></slot>
3243
3297
  </odx-dropdown>
3244
3298
  `;
@@ -3274,6 +3328,9 @@ const _OdxSelect = class _OdxSelect extends ListboxFormControl {
3274
3328
  __decorateClass([
3275
3329
  queryAssignedElements({ selector: '[role="option"]', flatten: true })
3276
3330
  ], _OdxSelect.prototype, "options", 2);
3331
+ __decorateClass([
3332
+ query(".base", true)
3333
+ ], _OdxSelect.prototype, "trigger", 2);
3277
3334
  __decorateClass([
3278
3335
  query(OdxDropdown.tagName, true)
3279
3336
  ], _OdxSelect.prototype, "dropdown", 2);
@@ -4259,13 +4316,15 @@ const _OdxTooltip = class _OdxTooltip extends PopoverHost {
4259
4316
  if (event.relatedTarget === this) return;
4260
4317
  this.#handleMouseEvents(event);
4261
4318
  };
4262
- this.#handleMouseEvents = ({ type }) => {
4263
- if (type !== "mouseenter" && type !== "mouseleave") return;
4264
- this.togglePopover(type === "mouseenter");
4319
+ this.#handleMouseEvents = (event) => {
4320
+ if (event.type !== "mouseenter" && event.type !== "mouseleave") return;
4321
+ this.updateReferenceElementFromEvent(event);
4322
+ this.togglePopover(event.type === "mouseenter");
4265
4323
  };
4266
- this.#handleKeyboardFocus = ({ type, key }) => {
4267
- if (key !== "Tab") return;
4268
- this.togglePopover(type !== "keydown");
4324
+ this.#handleKeyboardFocus = (event) => {
4325
+ if (event.key !== "Tab") return;
4326
+ this.updateReferenceElementFromEvent(event);
4327
+ this.togglePopover(event.type !== "keydown");
4269
4328
  };
4270
4329
  }
4271
4330
  static {
@@ -4287,9 +4346,10 @@ const _OdxTooltip = class _OdxTooltip extends PopoverHost {
4287
4346
  clearTimeout(this.#timeout);
4288
4347
  }
4289
4348
  mountPopover(referenceElement) {
4349
+ super.mountPopover?.(referenceElement);
4290
4350
  if (!referenceElement) return;
4291
- super.mountPopover(referenceElement);
4292
4351
  this.#updateAriaAttributes(referenceElement, this.id);
4352
+ if (this.popover === "manual") return;
4293
4353
  this.addEventListener("mouseleave", this.#handleMouseEvents);
4294
4354
  referenceElement.addEventListener("mouseenter", this.#handleMouseEvents);
4295
4355
  referenceElement.addEventListener("mouseleave", this.#handleReferenceMouseLeave);
@@ -4299,7 +4359,7 @@ const _OdxTooltip = class _OdxTooltip extends PopoverHost {
4299
4359
  referenceElement.addEventListener("keydown", this.#handleKeyboardFocus);
4300
4360
  }
4301
4361
  unmountPopover(referenceElement) {
4302
- super.unmountPopover(referenceElement);
4362
+ super.unmountPopover?.(referenceElement);
4303
4363
  this.#updateAriaAttributes(referenceElement, null);
4304
4364
  referenceElement.removeEventListener("keyup", this.#handleKeyboardFocus);
4305
4365
  referenceElement.removeEventListener("keydown", this.#handleKeyboardFocus);
@@ -4323,7 +4383,6 @@ const _OdxTooltip = class _OdxTooltip extends PopoverHost {
4323
4383
  this.#updateAriaAttributes(this.referenceElement, this.id);
4324
4384
  }
4325
4385
  if (props.has("show")) {
4326
- this.popover = this.show ? "manual" : "auto";
4327
4386
  this.togglePopover(this.show);
4328
4387
  }
4329
4388
  }
@@ -10,7 +10,7 @@ export interface GetAssignedElementOptions {
10
10
  selector?: string;
11
11
  flatten?: boolean;
12
12
  }
13
- export declare function getAssignedElement<T = HTMLElement>(root: Element, options?: GetAssignedElementOptions): T | undefined;
13
+ export declare function getAssignedElement<T = HTMLElement>(root: Element | ShadowRoot | null, options?: GetAssignedElementOptions): T | undefined;
14
14
  export declare function getKeyInfo(event: KeyboardEvent): {
15
15
  up: boolean;
16
16
  right: boolean;
package/dist/main.js CHANGED
@@ -74,7 +74,7 @@ function toPx(value) {
74
74
  function getAssignedElement(root, options) {
75
75
  const { slot, selector } = options ?? {};
76
76
  const slotSelector = `slot${slot ? `[name=${slot}]` : ":not([name])"}`;
77
- const slotEl = root.querySelector(slotSelector);
77
+ const slotEl = root?.querySelector(slotSelector);
78
78
  const elements = slotEl?.assignedElements(options) ?? [];
79
79
  if (selector == null) {
80
80
  return elements[0];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@odx/foundation",
3
3
  "description": "A library of Web Component building blocks for ODX",
4
- "version": "1.0.0-beta.81",
4
+ "version": "1.0.0-beta.83",
5
5
  "author": "Drägerwerk AG & Co.KGaA",
6
6
  "license": "SEE LICENSE IN LICENSE",
7
7
  "homepage": "https://odx.draeger.com",