@odx/foundation 1.0.0-beta.98 → 1.0.0-beta.99

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.
@@ -17,7 +17,7 @@ export declare class OdxAutocomplete extends FormControl {
17
17
  searchFn: (option: OptionControl, query?: string) => boolean;
18
18
  get control(): HTMLInputElement | undefined;
19
19
  get controlValue(): string;
20
- firstUpdated(props: PropertyValues<this>): void;
20
+ protected firstUpdated(props: PropertyValues<this>): void;
21
21
  protected render(): TemplateResult;
22
22
  }
23
23
  //# sourceMappingURL=autocomplete.d.ts.map
@@ -18,7 +18,6 @@ export declare class OdxInput extends FormControl<string> {
18
18
  step?: number;
19
19
  type: HTMLInputElement['type'];
20
20
  value: string;
21
- clear(): void;
22
21
  stepUp(): void;
23
22
  stepDown(): void;
24
23
  protected willUpdate(props: PropertyValues<this>): void;
@@ -6,6 +6,7 @@ export declare abstract class PopoverHost extends PopoverHost_base {
6
6
  #private;
7
7
  static readonly styles: import('lit').CSSResult;
8
8
  protected popoverElement: OdxPopover;
9
+ open: boolean;
9
10
  set referenceElement(value: HTMLElement | null);
10
11
  get referenceElement(): HTMLElement | null;
11
12
  placement: Placement;
@@ -17,7 +18,7 @@ export declare abstract class PopoverHost extends PopoverHost_base {
17
18
  hasMountedPopover(element: HTMLElement): boolean;
18
19
  mountPopover(referenceElement: HTMLElement | null): void;
19
20
  unmountPopover(_referenceElement: HTMLElement): void;
20
- isPopoverOpen(): boolean;
21
+ hasOpenPopover(referenceElement: HTMLElement | null): boolean;
21
22
  showPopover(): Promise<void>;
22
23
  hidePopover(): void;
23
24
  togglePopover(state?: boolean): boolean;
@@ -13,11 +13,13 @@ export declare class OdxSelect extends ListboxFormControl<OptionControl> {
13
13
  protected readonly dropdown: OdxDropdown;
14
14
  maxVisibleSelectedOptions: number;
15
15
  constructor();
16
- connectedCallback(): void;
17
- firstUpdated(props: PropertyValues<this>): void;
16
+ clear(): void;
18
17
  isDropdownOpen(): boolean;
19
18
  showDropdown(): void;
20
19
  hideDropdown(): void;
20
+ connectedCallback(): void;
21
+ firstUpdated(props: PropertyValues<this>): void;
22
+ protected canSelect(option: OptionControl): boolean;
21
23
  protected render(): TemplateResult;
22
24
  protected updated(props: PropertyValues<this>): void;
23
25
  }
@@ -12,6 +12,7 @@ export declare class OdxSpinbox extends FormControl<string> {
12
12
  selectedIndex: number;
13
13
  value: string;
14
14
  constructor();
15
+ clear(): void;
15
16
  protected willUpdate(props: PropertyValues<this>): void;
16
17
  protected updated(props: PropertyValues<this>): void;
17
18
  previous(): void;
@@ -964,7 +964,7 @@ __decorateClass([
964
964
  ], _OdxCircularProgressBar.prototype, "size", 2);
965
965
  let OdxCircularProgressBar = _OdxCircularProgressBar;
966
966
 
967
- 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)}}}";
967
+ 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: 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: calc(-1 * 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: calc(-1 * 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: 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)}}}";
968
968
 
969
969
  const popoverTargetAttribute = "odx-popovertarget";
970
970
  class PopoverObserver {
@@ -1003,10 +1003,12 @@ class PopoverHost extends CanBeDisabled(CustomElement) {
1003
1003
  super();
1004
1004
  this.#currentReferenceElement = null;
1005
1005
  this.#openPopovers = /* @__PURE__ */ new WeakSet();
1006
+ this.open = false;
1006
1007
  this.placement = Placement.BOTTOM;
1007
1008
  this.fpsLimit = 60;
1008
1009
  this.#handleToggle = async (event) => {
1009
- if (this.isPopoverOpen()) {
1010
+ this.open = !!this.referenceElement && event.newState === "open";
1011
+ if (this.hasOpenPopover(this.referenceElement)) {
1010
1012
  await this.onBeforePopoverShow?.();
1011
1013
  await waitForAnimations(this);
1012
1014
  await this.onPopoverShow?.();
@@ -1016,7 +1018,7 @@ class PopoverHost extends CanBeDisabled(CustomElement) {
1016
1018
  await this.onPopoverHide?.();
1017
1019
  }
1018
1020
  if (!this.referenceElement) return;
1019
- if (event.newState === "open") {
1021
+ if (this.open) {
1020
1022
  this.#openPopovers.add(this.referenceElement);
1021
1023
  } else {
1022
1024
  this.#openPopovers.delete(this.referenceElement);
@@ -1065,16 +1067,15 @@ class PopoverHost extends CanBeDisabled(CustomElement) {
1065
1067
  unmountPopover(_referenceElement) {
1066
1068
  this.referenceElement = null;
1067
1069
  }
1068
- isPopoverOpen() {
1069
- return !!this.referenceElement && this.#openPopovers.has(this.referenceElement);
1070
+ hasOpenPopover(referenceElement) {
1071
+ return !!referenceElement && this.#openPopovers.has(referenceElement);
1070
1072
  }
1071
1073
  async showPopover() {
1072
1074
  if (!this.referenceElement || this.disabled || this.canPopoverShow?.() === false) return;
1073
1075
  await 0;
1076
+ this.#positionUpdater?.();
1074
1077
  computePopoverPlacement(this.referenceElement, this, this.options);
1075
1078
  super.showPopover();
1076
- this.#openPopovers.add(this.referenceElement);
1077
- this.#positionUpdater?.();
1078
1079
  this.#positionUpdater = autoUpdate(
1079
1080
  this.referenceElement,
1080
1081
  this,
@@ -1082,16 +1083,13 @@ class PopoverHost extends CanBeDisabled(CustomElement) {
1082
1083
  );
1083
1084
  }
1084
1085
  hidePopover() {
1085
- if (!this.isPopoverOpen() || this.canPopoverHide?.() === false) return;
1086
- this.#positionUpdater?.();
1086
+ if (!this.open || this.canPopoverHide?.() === false) return;
1087
1087
  super.hidePopover();
1088
- if (this.referenceElement) {
1089
- this.#openPopovers.delete(this.referenceElement);
1090
- }
1088
+ this.#positionUpdater?.();
1091
1089
  this.#positionUpdater = void 0;
1092
1090
  }
1093
1091
  togglePopover(state) {
1094
- const isOpen = state ?? !this.isPopoverOpen();
1092
+ const isOpen = state ?? !this.hasOpenPopover(this.referenceElement);
1095
1093
  if (isOpen) {
1096
1094
  this.showPopover();
1097
1095
  } else {
@@ -1106,9 +1104,9 @@ class PopoverHost extends CanBeDisabled(CustomElement) {
1106
1104
  }
1107
1105
  willUpdate(props) {
1108
1106
  super.willUpdate(props);
1109
- if (props.has("referenceElement") && this.referenceElement !== props.get("referenceElement")) {
1107
+ if (props.has("referenceElement")) {
1110
1108
  const previousReferenceElement = props.get("referenceElement");
1111
- if (previousReferenceElement) {
1109
+ if (previousReferenceElement && this.referenceElement !== previousReferenceElement) {
1112
1110
  this.#openPopovers.delete(previousReferenceElement);
1113
1111
  }
1114
1112
  }
@@ -1127,6 +1125,9 @@ class PopoverHost extends CanBeDisabled(CustomElement) {
1127
1125
  __decorateClass([
1128
1126
  query("odx-popover", true)
1129
1127
  ], PopoverHost.prototype, "popoverElement", 2);
1128
+ __decorateClass([
1129
+ property({ type: Boolean, reflect: true, useDefault: true })
1130
+ ], PopoverHost.prototype, "open", 2);
1130
1131
  __decorateClass([
1131
1132
  property({ attribute: false })
1132
1133
  ], PopoverHost.prototype, "referenceElement", 1);
@@ -1145,17 +1146,19 @@ const _OdxDropdown = class _OdxDropdown extends PopoverHost {
1145
1146
  super(...arguments);
1146
1147
  this.matchReferenceWidth = false;
1147
1148
  this.placement = DropdownPlacement.BOTTOM;
1148
- this.#handleClick = (event) => {
1149
- if (event?.defaultPrevented) return;
1149
+ this.#handleInteraction = (event) => {
1150
+ if (event.defaultPrevented) return;
1150
1151
  this.updateReferenceElementFromEvent(event);
1151
1152
  this.togglePopover();
1152
1153
  };
1153
1154
  this.#handleKeyboardEvent = (event) => {
1154
1155
  const key = getKeyInfo(event);
1155
- if (!key.enter || event.defaultPrevented) return;
1156
- if (!this.isPopoverOpen()) {
1156
+ if (!(key.enter || key.space) || event.defaultPrevented) return;
1157
+ if (!this.open) {
1158
+ event.preventDefault();
1157
1159
  event.stopImmediatePropagation();
1158
1160
  }
1161
+ this.updateReferenceElementFromEvent(event);
1159
1162
  this.showPopover();
1160
1163
  };
1161
1164
  }
@@ -1176,14 +1179,14 @@ const _OdxDropdown = class _OdxDropdown extends PopoverHost {
1176
1179
  super.mountPopover(referenceElement);
1177
1180
  if (!referenceElement) return;
1178
1181
  this.#updateAriaAttributes(referenceElement, this.id);
1179
- referenceElement.addEventListener("click", this.#handleClick);
1182
+ referenceElement.addEventListener("click", this.#handleInteraction);
1180
1183
  referenceElement.addEventListener("keydown", this.#handleKeyboardEvent);
1181
1184
  }
1182
1185
  unmountPopover(referenceElement) {
1183
1186
  super.unmountPopover(referenceElement);
1184
1187
  if (!referenceElement) return;
1185
1188
  this.#updateAriaAttributes(referenceElement, null);
1186
- referenceElement.removeEventListener("click", this.#handleClick);
1189
+ referenceElement.removeEventListener("click", this.#handleInteraction);
1187
1190
  referenceElement.removeEventListener("keydown", this.#handleKeyboardEvent);
1188
1191
  }
1189
1192
  render() {
@@ -1207,7 +1210,7 @@ const _OdxDropdown = class _OdxDropdown extends PopoverHost {
1207
1210
  referenceElement.removeAttribute(ariaAttribute);
1208
1211
  }
1209
1212
  }
1210
- #handleClick;
1213
+ #handleInteraction;
1211
1214
  #handleKeyboardEvent;
1212
1215
  };
1213
1216
  __decorateClass([
@@ -1334,7 +1337,7 @@ const _OdxAutocomplete = class _OdxAutocomplete extends FormControl {
1334
1337
  this.dropdown.hidePopover();
1335
1338
  };
1336
1339
  this.#handleControlClear = () => {
1337
- if (!this.dropdown.isPopoverOpen()) return;
1340
+ if (!this.dropdown.open) return;
1338
1341
  this.#handleControlValueChange(void 0);
1339
1342
  };
1340
1343
  this.#handleControlInput = () => {
@@ -1343,7 +1346,7 @@ const _OdxAutocomplete = class _OdxAutocomplete extends FormControl {
1343
1346
  } else if (this.controlValue.length === 0) {
1344
1347
  this.dropdown.hidePopover();
1345
1348
  }
1346
- if (!this.dropdown.isPopoverOpen()) return;
1349
+ if (!this.dropdown.open) return;
1347
1350
  this.#handleControlValueChange(this.controlValue);
1348
1351
  };
1349
1352
  this.#handleControlKeyboardEvent = (event) => {
@@ -1958,23 +1961,25 @@ const _OdxInput = class _OdxInput extends FormControl {
1958
1961
  this.placeholder = "";
1959
1962
  this.type = "text";
1960
1963
  this.value = "";
1964
+ this.#handleClear = (event) => {
1965
+ if (!this.#isClearable()) return;
1966
+ event.preventDefault();
1967
+ event.stopPropagation();
1968
+ if (this.emit("clear")) return;
1969
+ this.clear();
1970
+ };
1961
1971
  this.#handleInput = (event) => {
1962
1972
  this.value = event.target.value;
1963
1973
  };
1964
1974
  this.#handleKeyDown = (event) => {
1965
- if (!getKeyInfo(event).escape) return;
1966
- event.preventDefault();
1967
- this.clear();
1975
+ const key = getKeyInfo(event);
1976
+ if (!key.escape) return;
1977
+ this.#handleClear(event);
1968
1978
  };
1969
1979
  }
1970
1980
  static {
1971
1981
  customElement("odx-input", styles$M)(_OdxInput);
1972
1982
  }
1973
- clear() {
1974
- if (!this.#isClearable() || this.emit("clear")) return;
1975
- this.value = "";
1976
- this.focus();
1977
- }
1978
1983
  stepUp() {
1979
1984
  if (!this.nativeInput) return;
1980
1985
  this.nativeInput.stepUp();
@@ -2027,7 +2032,7 @@ const _OdxInput = class _OdxInput extends FormControl {
2027
2032
  ${this.renderControl("increment", "core::plus", () => this.stepUp(), this.disabled || !canStepUp)}
2028
2033
  </odx-button-group>
2029
2034
  `,
2030
- () => when(!(this.disabled || this.readonly) && this.clearable, () => this.renderControl("clear", "core::cancel", () => this.clear(), this.disabled))
2035
+ () => when(this.#isClearable(), () => this.renderControl("clear", "core::cancel", this.#handleClear, this.disabled))
2031
2036
  )}
2032
2037
  <slot name="suffix"></slot>
2033
2038
  `;
@@ -2042,6 +2047,7 @@ const _OdxInput = class _OdxInput extends FormControl {
2042
2047
  #isClearable() {
2043
2048
  return this.clearable && !this.disabled && !this.readonly && !this.required && !!this.value;
2044
2049
  }
2050
+ #handleClear;
2045
2051
  #handleInput;
2046
2052
  #handleKeyDown;
2047
2053
  };
@@ -2572,7 +2578,7 @@ class OdxMenu extends PopoverHost {
2572
2578
  };
2573
2579
  #handleKeyDown = (event) => {
2574
2580
  const key = getKeyInfo(event);
2575
- if (!(this.isPopoverOpen() && (key.tab || key.backTab))) return;
2581
+ if (!(this.open && (key.tab || key.backTab))) return;
2576
2582
  event?.preventDefault();
2577
2583
  event.stopPropagation();
2578
2584
  this.hidePopover();
@@ -2615,7 +2621,7 @@ __decorateClass([
2615
2621
  ], _OdxMenuItem.prototype, "icon", 2);
2616
2622
  let OdxMenuItem = _OdxMenuItem;
2617
2623
 
2618
- const styles$A = "@layer base{:host{--max-inline-size: 640px;--margin-block-start: var(--odx-size-450);--_modal-transition: var(--odx-popover-transition, var(--odx-motion-duration-default));--_modal-transition-offset-x: 0;--_modal-transition-offset-y: calc(-1 * var(--_modal-offset));--_modal-outer-padding: var(--odx-breakpoint-spacing-150);display:contents;transition-property:display}:host,.base,.base::backdrop{transition:var(--odx-transition-default);transition-behavior:allow-discrete}.base,.base::backdrop{opacity:0}.base{transform:translateY(var(--odx-size-100));transition-property:opacity,display,overlay,transform,outline;margin-block-start:var(--margin-block-start);border:0;border-radius:var(--odx-border-radius-ml);box-shadow:var(--odx-shadow-level-2);background:transparent;padding:0;inline-size:min(var(--max-inline-size),100% - 2 * var(--_modal-outer-padding));overflow:unset;color:var(--odx-color-foreground-rest);&::backdrop{transition-property:opacity;background-color:var(--odx-color-backdrop);backdrop-filter:blur(var(--odx-elevation-blur))}}.inner{display:flex;flex-direction:column;border-radius:inherit;background-color:var(--odx-color-background-level-1);padding:var(--odx-spacing-50) var(--odx-breakpoint-spacing-150);max-block-size:calc(100dvh - 2 * var(--_modal-outer-padding))}.header,.footer{min-block-size:var(--odx-size-300)}.content{padding:var(--odx-size-75) 0}.dismiss-action{margin-inline-start:auto}}@layer state{:host(:not([open])){display:none}.base:focus-visible{outline-color:var(--odx-color-stroke-focus-outer)}.base[open]{transform:translate(0);&,&::backdrop{opacity:1;@starting-style{opacity:0}}@starting-style{transform:translateY(var(--odx-size-100))}}}";
2624
+ const styles$A = "@layer base{:host{--max-inline-size: 640px;--_modal-outer-padding: var(--odx-breakpoint-spacing-150);display:contents;transition-property:display}:host,.base,.base::backdrop{transition:var(--odx-transition-slow);transition-behavior:allow-discrete}.base,.base::backdrop{opacity:0}.base{transform:translateY(var(--odx-size-100));transition-property:opacity,display,overlay,transform,box-shadow;border:0;border-radius:var(--odx-border-radius-ml);background:transparent;padding:0;inline-size:min(var(--max-inline-size),100% - 2 * var(--_modal-outer-padding));overflow:unset;color:var(--odx-color-foreground-rest);&::backdrop{transition-property:opacity;background-color:var(--odx-color-backdrop);backdrop-filter:blur(var(--odx-elevation-blur))}}.inner{display:flex;flex-direction:column;border-radius:inherit;background-color:var(--odx-color-background-level-1);padding:var(--odx-spacing-50) var(--odx-breakpoint-spacing-150);max-block-size:calc(100dvh - 2 * var(--_modal-outer-padding))}.header,.footer{min-block-size:var(--odx-size-300)}.content{padding:var(--odx-size-75) 0;overflow:auto}.dismiss-action{margin-inline-start:auto}}@layer state{:host(:not([open])){display:none}.base:focus-visible{outline-color:var(--odx-color-stroke-focus-outer)}.base[open]{transform:translate(0);box-shadow:var(--odx-shadow-level-2);&,&::backdrop{opacity:1;@starting-style{opacity:0}}@starting-style{transform:translateY(var(--odx-size-100))}}}";
2619
2625
 
2620
2626
  const ModalLayout = { MODAL: "modal", SIDESHEET: "sidesheet" };
2621
2627
  (async () => {
@@ -3256,7 +3262,7 @@ __decorateClass([
3256
3262
  ], _OdxSearchBar.prototype, "readonly", 2);
3257
3263
  let OdxSearchBar = _OdxSearchBar;
3258
3264
 
3259
- const styles$o = "@layer base{:host{--_color-background: var(--odx-color-background-control-rest);--_color-foreground: var(--odx-color-foreground-rest);--_color-stroke: var(--odx-color-stroke-control-rest);--_control-size: var(--odx-size-225);--_padding-block: var(--odx-size-37);--_padding-inline: var(--odx-size-50);display:block;border-radius:var(--odx-border-radius-controls);cursor:pointer;inline-size:100%;max-inline-size:320px;overflow:hidden;color:var(--_color-foreground)}.base{display:flex;gap:var(--_padding-block);align-items:center;transition:var(--odx-transition-reduced);transition-property:background-color,border-color;border:var(--odx-border-width-thin) solid transparent;border-bottom-color:var(--_color-stroke);background-color:var(--_color-background);padding-inline:var(--_padding-inline);block-size:var(--_control-size);min-width:200px;overflow:hidden;text-align:start;user-select:none;&:focus-visible{outline:var(--odx-focus-ring-outline);outline-color:var(--odx-color-stroke-focus-outer)}}.value{margin-inline-end:auto;font-weight:var(--odx-typography-font-weight-medium)}.indicator{font-size:var(--odx-typography-font-size-6)}[part~=dropdown]{--max-block-size: 320px}odx-chip{--_border-radius: var(--odx-border-radius-controls)}slot[name=placeholder]{color:var(--odx-color-foreground-rest-subtle);font-weight:var(--odx-typography-font-weight-normal)}}@layer state{:host(:hover){--_color-background: var(--odx-color-background-control-hover);--_color-stroke: var(--odx-color-stroke-control-hover)}:host([multiple]):has(odx-chip) .base{padding-inline-start:var(--_padding-block)}:host([disabled]:not([readonly])){--_color-foreground: var(--odx-color-foreground-disabled-rest);--_color-background: var(--odx-color-background-disabled-rest);--_color-stroke: var(--odx-color-stroke-disabled-rest);cursor:not-allowed;slot[name=placeholder]{color:var(---_color-foreground)}}:host([readonly]){--_color-background: var(--odx-color-background-control-readonly);--_color-stroke: var(--odx-color-stroke-control-readonly);cursor:default;odx-chip{--_color-background: var(--odx-color-foreground-disabled-rest)}.indicator{color:var(--odx-color-foreground-rest-subtle)}}}";
3265
+ const styles$o = "@layer base{:host{--_color-background: var(--odx-color-background-control-rest);--_color-foreground: var(--odx-color-foreground-rest);--_color-stroke: var(--odx-color-stroke-control-rest);--_control-size: var(--odx-size-225);--_padding-block: var(--odx-size-37);--_padding-inline: var(--odx-size-50);display:block;border-radius:var(--odx-border-radius-controls);cursor:pointer;inline-size:100%;max-inline-size:320px;overflow:hidden;color:var(--_color-foreground)}.base{display:flex;gap:var(--_padding-block);align-items:center;transition:var(--odx-transition-reduced);transition-property:background-color,border-color;border:var(--odx-border-width-thin) solid transparent;border-bottom-color:var(--_color-stroke);background-color:var(--_color-background);padding-inline:var(--_padding-inline);block-size:var(--_control-size);min-width:200px;overflow:hidden;text-align:start;user-select:none;&:focus-visible{outline:var(--odx-focus-ring-outline);outline-color:var(--odx-color-stroke-focus-outer)}}.value{margin-inline-end:auto;font-weight:var(--odx-typography-font-weight-medium)}.indicator{font-size:var(--odx-typography-font-size-6)}[part~=dropdown]{--max-block-size: 320px}odx-chip{--_border-radius: var(--odx-border-radius-controls)}slot[name=placeholder]{color:var(--odx-color-foreground-rest-subtle);font-weight:var(--odx-typography-font-weight-normal)}:host:has(odx-dropdown[open]){--_color-background: var(--odx-color-background-control-hover);--_color-stroke: var(--odx-color-stroke-control-hover)}}@layer state{:host(:hover){--_color-background: var(--odx-color-background-control-hover);--_color-stroke: var(--odx-color-stroke-control-hover)}:host([multiple]):has(odx-chip) .base{padding-inline-start:var(--_padding-block)}:host([disabled]:not([readonly])){--_color-foreground: var(--odx-color-foreground-disabled-rest);--_color-background: var(--odx-color-background-disabled-rest);--_color-stroke: var(--odx-color-stroke-disabled-rest);cursor:not-allowed;slot[name=placeholder]{color:var(---_color-foreground)}}:host([readonly]){--_color-background: var(--odx-color-background-control-readonly);--_color-stroke: var(--odx-color-stroke-control-readonly);cursor:default;odx-chip{--_color-background: var(--odx-color-foreground-disabled-rest)}.indicator{color:var(--odx-color-foreground-rest-subtle)}}}";
3260
3266
 
3261
3267
  const _OdxSelect = class _OdxSelect extends ListboxFormControl {
3262
3268
  constructor() {
@@ -3278,13 +3284,13 @@ const _OdxSelect = class _OdxSelect extends ListboxFormControl {
3278
3284
  this.value = this.value.length === this.options.length ? [] : this.options.map((option) => option.value);
3279
3285
  };
3280
3286
  this.#handleClear = (event) => {
3281
- event.stopPropagation();
3282
3287
  event.preventDefault();
3283
- if (!this.#isClearable() || this.emit("clear")) return;
3284
- this.updateValue(void 0);
3288
+ event.stopPropagation();
3289
+ if (this.emit("clear")) return;
3290
+ this.clear();
3285
3291
  };
3286
3292
  this.#handleSelect = () => {
3287
- if (this.autoSelect && !this.isDropdownOpen() || this.multiple) return;
3293
+ if (this.autoSelect || this.multiple) return;
3288
3294
  this.hideDropdown();
3289
3295
  };
3290
3296
  if (!isServer) {
@@ -3295,16 +3301,11 @@ const _OdxSelect = class _OdxSelect extends ListboxFormControl {
3295
3301
  static {
3296
3302
  customElement("odx-select", styles$o)(_OdxSelect);
3297
3303
  }
3298
- connectedCallback() {
3299
- super.connectedCallback();
3300
- this.role = "combobox";
3301
- }
3302
- firstUpdated(props) {
3303
- super.firstUpdated(props);
3304
- this.dropdown.mountPopover(this.shadowRoot?.querySelector(".base") ?? null);
3304
+ clear() {
3305
+ this.value = this.multiple ? [] : "";
3305
3306
  }
3306
3307
  isDropdownOpen() {
3307
- return this.dropdown?.isPopoverOpen();
3308
+ return this.dropdown.open;
3308
3309
  }
3309
3310
  showDropdown() {
3310
3311
  this.dropdown.showPopover();
@@ -3312,6 +3313,17 @@ const _OdxSelect = class _OdxSelect extends ListboxFormControl {
3312
3313
  hideDropdown() {
3313
3314
  this.dropdown.hidePopover();
3314
3315
  }
3316
+ connectedCallback() {
3317
+ super.connectedCallback();
3318
+ this.role = "combobox";
3319
+ }
3320
+ firstUpdated(props) {
3321
+ super.firstUpdated(props);
3322
+ this.dropdown.mountPopover(this.shadowRoot?.querySelector(".base") ?? null);
3323
+ }
3324
+ canSelect(option) {
3325
+ return (this.autoSelect || this.dropdown.open) && super.canSelect(option);
3326
+ }
3315
3327
  render() {
3316
3328
  const allSelected = this.value.length === this.options.length;
3317
3329
  const dropdownDisabled = this.disabled || this.readonly && (!this.multiple || this.selectedOptions.length === 0);
@@ -3779,6 +3791,9 @@ const _OdxSpinbox = class _OdxSpinbox extends FormControl {
3779
3791
  delegatesFocus: false
3780
3792
  };
3781
3793
  }
3794
+ clear() {
3795
+ this.value = "";
3796
+ }
3782
3797
  willUpdate(props) {
3783
3798
  super.willUpdate(props);
3784
3799
  if (props.has("selectedIndex")) {
@@ -8,6 +8,7 @@ export declare abstract class CheckboxFormControl extends FormControl<string> {
8
8
  value: string;
9
9
  constructor();
10
10
  toFormValue(): string | File | FormData | null;
11
+ clear(): void;
11
12
  toggle(state?: boolean, emitEvent?: boolean): void;
12
13
  connectedCallback(): void;
13
14
  updateAriaAttributes(): void;
@@ -10,11 +10,12 @@ export declare abstract class CheckboxGroupFormControl extends FormControl<strin
10
10
  get groupControl(): CheckboxFormControl | null;
11
11
  value: string[];
12
12
  constructor();
13
- protected firstUpdated(_changedProperties: PropertyValues): Promise<void>;
13
+ clear(): void;
14
14
  toFormValue(): FormData;
15
15
  protected isControl(element: unknown): element is CheckboxFormControl;
16
16
  protected isGroupControl(element: unknown): element is CheckboxFormControl;
17
17
  protected isControlChecked(control: CheckboxFormControl): boolean;
18
+ protected firstUpdated(_changedProperties: PropertyValues): Promise<void>;
18
19
  protected updated(props: PropertyValues<this>): void;
19
20
  protected updateControls(updateFn: (control: CheckboxFormControl, index: number) => void): void;
20
21
  protected updateValue(value: string[], dispatchEvent?: boolean): void;
@@ -2,7 +2,7 @@ import { PropertyValues } from 'lit';
2
2
  import { CustomElement } from '../custom-element.js';
3
3
  import { CanBeDisabled } from '../mixins/can-be-disabled.js';
4
4
  declare const FormControl_base: import('../main.js').Constructor<CanBeDisabled> & typeof CustomElement;
5
- export declare class FormControl<V extends string | number | string[] = string> extends FormControl_base {
5
+ export declare abstract class FormControl<V extends string | number | string[] = string> extends FormControl_base {
6
6
  /** @internal */
7
7
  static readonly formAssociated = true;
8
8
  /** @internal */
@@ -23,6 +23,7 @@ export declare class FormControl<V extends string | number | string[] = string>
23
23
  checkValidity(): boolean;
24
24
  setValidity(flags?: ValidityStateFlags, target?: HTMLElement): void;
25
25
  reportValidity(): void;
26
+ clear(): void;
26
27
  protected willUpdate(props: PropertyValues<this>): void;
27
28
  }
28
29
  export {};
@@ -16,6 +16,7 @@ export declare abstract class ListboxFormControl<Option extends OptionControl> e
16
16
  protected canAutoSelect(option: Option): boolean;
17
17
  protected canSelect(option: Option): boolean;
18
18
  toggleOption(option: Option, state?: boolean): void;
19
+ clear(): void;
19
20
  connectedCallback(): void;
20
21
  protected handleSlotChange(): void;
21
22
  protected updateValue(option?: Option): void;
@@ -5,6 +5,7 @@ export declare class NumberFormControl extends FormControl<number> {
5
5
  max: number;
6
6
  step: number;
7
7
  value: number;
8
+ clear(): void;
8
9
  getValueText(): string;
9
10
  protected willUpdate(props: PropertyValues<this>): void;
10
11
  toFormValue(): string;
package/dist/main.js CHANGED
@@ -177,6 +177,9 @@ class FormControl extends CanBeDisabled(CustomElement) {
177
177
  reportValidity() {
178
178
  this.internals.reportValidity();
179
179
  }
180
+ clear() {
181
+ this.value = "";
182
+ }
180
183
  willUpdate(props) {
181
184
  super.willUpdate(props);
182
185
  if (props.has("required")) {
@@ -238,6 +241,9 @@ class CheckboxFormControl extends FormControl {
238
241
  }
239
242
  return this.checked ? "on" : null;
240
243
  }
244
+ clear() {
245
+ this.checked = false;
246
+ }
241
247
  toggle(state, emitEvent = false) {
242
248
  const currentState = this.checked;
243
249
  const newState = state ?? !currentState;
@@ -302,9 +308,8 @@ const _CheckboxGroupFormControl = class _CheckboxGroupFormControl extends FormCo
302
308
  get groupControl() {
303
309
  return this.#findControls((element) => element.hasAttribute(GROUP_CONTROL_SELECTOR))[0] ?? null;
304
310
  }
305
- async firstUpdated(_changedProperties) {
306
- await 0;
307
- this.value = this.controls.filter((control) => control.checked).map((control) => control.value);
311
+ clear() {
312
+ this.value = [];
308
313
  }
309
314
  toFormValue() {
310
315
  const formData = new FormData();
@@ -322,6 +327,10 @@ const _CheckboxGroupFormControl = class _CheckboxGroupFormControl extends FormCo
322
327
  isControlChecked(control) {
323
328
  return this.value.includes(control.value);
324
329
  }
330
+ async firstUpdated(_changedProperties) {
331
+ await 0;
332
+ this.value = this.controls.filter((control) => control.checked).map((control) => control.value);
333
+ }
325
334
  updated(props) {
326
335
  super.updated(props);
327
336
  if (props.has("value")) {
@@ -341,11 +350,17 @@ const _CheckboxGroupFormControl = class _CheckboxGroupFormControl extends FormCo
341
350
  });
342
351
  }
343
352
  if (props.has("disabled")) {
353
+ if (this.groupControl) {
354
+ this.groupControl.disabled = this.disabled;
355
+ }
344
356
  this.updateControls((control) => {
345
357
  control.disabled = this.disabled;
346
358
  });
347
359
  }
348
360
  if (props.has("readonly")) {
361
+ if (this.groupControl) {
362
+ this.groupControl.readonly = this.disabled;
363
+ }
349
364
  this.updateControls((control) => {
350
365
  control.readonly = this.readonly;
351
366
  });
@@ -525,9 +540,9 @@ class ListboxFormControl extends FormControl {
525
540
  super();
526
541
  this.activeDescendants = new ActiveDescendantsController(this, {
527
542
  getItems: () => this.options,
528
- onChange: (_, option, firstChange) => {
543
+ onChange: (_, option) => {
529
544
  option?.scrollIntoView();
530
- if (!(option && this.canAutoSelect(option)) || firstChange || option.selected) return;
545
+ if (!(option && this.canAutoSelect(option)) || option.selected) return;
531
546
  this.toggleOption(option, true);
532
547
  }
533
548
  });
@@ -589,6 +604,9 @@ class ListboxFormControl extends FormControl {
589
604
  option.scrollIntoView();
590
605
  }
591
606
  }
607
+ clear() {
608
+ this.value = this.multiple ? [] : "";
609
+ }
592
610
  connectedCallback() {
593
611
  super.connectedCallback();
594
612
  this.role ||= "listbox";
@@ -674,6 +692,9 @@ class NumberFormControl extends FormControl {
674
692
  this.step = 1;
675
693
  this.value = 0;
676
694
  }
695
+ clear() {
696
+ this.value = 0;
697
+ }
677
698
  getValueText() {
678
699
  return this.ariaValueText?.trim() ?? "";
679
700
  }
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.98",
4
+ "version": "1.0.0-beta.99",
5
5
  "author": "Drägerwerk AG & Co.KGaA",
6
6
  "license": "SEE LICENSE IN LICENSE",
7
7
  "homepage": "https://odx.draeger.com",
@@ -40,8 +40,8 @@
40
40
  "ts-lit-plugin": "2.0.2",
41
41
  "vite": "6.3.5",
42
42
  "vite-plugin-dts": "4.5.4",
43
- "@odx/storybook-utils": "0.0.0",
44
- "@odx/typescript-config": "0.0.0"
43
+ "@odx/typescript-config": "0.0.0",
44
+ "@odx/storybook-utils": "0.0.0"
45
45
  },
46
46
  "sideEffects": [
47
47
  "dist/i18n.js",