@vonage/vivid 4.14.4 → 4.16.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.
@@ -1,6 +1,6 @@
1
1
  import type { Popup } from '../popup/popup';
2
2
  import type { Appearance, Shape, Size } from '../enums';
3
- import { AffixIcon, type FormElement } from '../../shared/patterns';
3
+ import { AffixIcon, type ErrorText, type FormElement, FormElementHelperText, FormElementSuccessText } from '../../shared/patterns';
4
4
  import type { ListboxOption } from '../option/option';
5
5
  import { FormAssociatedCombobox } from './combobox.form-associated';
6
6
  import { ComboboxAutocomplete } from './combobox.options';
@@ -31,5 +31,5 @@ export declare class Combobox extends FormAssociatedCombobox {
31
31
  connectedCallback(): void;
32
32
  filterOptions(): void;
33
33
  }
34
- export interface Combobox extends AffixIcon, FormElement {
34
+ export interface Combobox extends AffixIcon, FormElement, FormElementHelperText, ErrorText, FormElementSuccessText, FormElement {
35
35
  }
@@ -1 +1,5 @@
1
1
  export declare const roundToStepValue: (value: number, step: number) => number;
2
+ export declare const defaultToOneConverter: {
3
+ fromView(value: string | number): number;
4
+ toView(value: number): string;
5
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vonage/vivid",
3
- "version": "4.14.4",
3
+ "version": "4.16.0",
4
4
  "type": "module",
5
5
  "module": "./index.js",
6
6
  "main": "./index.cjs",
@@ -157,6 +157,11 @@ function renderIconOrPending(context, icon, pending, size = enums.Size.Normal) {
157
157
  return affixIconTemplate(icon, affix.IconWrapper.Slot);
158
158
  }
159
159
  }
160
+ const getButtonType = (type) => {
161
+ const types = ["submit", "button", "reset"];
162
+ if (types.indexOf(type) > -1) return type;
163
+ return "submit";
164
+ };
160
165
  const buttonContent = (context) => {
161
166
  const chevronTemplate = chevronTemplateFactory(context);
162
167
  return vividElement.html`<span class="content">
@@ -180,7 +185,7 @@ function renderButtonContent(context) {
180
185
  formnovalidate="${(x) => x.formnovalidate}"
181
186
  formtarget="${(x) => x.formtarget}"
182
187
  name="${(x) => x.name}"
183
- type="${(x) => x.type ?? "submit"}"
188
+ type="${(x) => getButtonType(x.type)}"
184
189
  value="${(x) => x.value}"
185
190
  aria-atomic="${(x) => x.ariaAtomic}"
186
191
  aria-busy="${(x) => x.ariaBusy}"
@@ -155,6 +155,11 @@ function renderIconOrPending(context, icon, pending, size = Size.Normal) {
155
155
  return affixIconTemplate(icon, IconWrapper.Slot);
156
156
  }
157
157
  }
158
+ const getButtonType = (type) => {
159
+ const types = ["submit", "button", "reset"];
160
+ if (types.indexOf(type) > -1) return type;
161
+ return "submit";
162
+ };
158
163
  const buttonContent = (context) => {
159
164
  const chevronTemplate = chevronTemplateFactory(context);
160
165
  return html`<span class="content">
@@ -178,7 +183,7 @@ function renderButtonContent(context) {
178
183
  formnovalidate="${(x) => x.formnovalidate}"
179
184
  formtarget="${(x) => x.formtarget}"
180
185
  name="${(x) => x.name}"
181
- type="${(x) => x.type ?? "submit"}"
186
+ type="${(x) => getButtonType(x.type)}"
182
187
  value="${(x) => x.value}"
183
188
  aria-atomic="${(x) => x.ariaAtomic}"
184
189
  aria-busy="${(x) => x.ariaBusy}"
@@ -5,7 +5,7 @@ const definition = require('./definition63.cjs');
5
5
  const definition$3 = require('./definition35.cjs');
6
6
  const textField = require('./text-field.cjs');
7
7
  const vividElement = require('./vivid-element.cjs');
8
- const applyMixins = require('./apply-mixins.cjs');
8
+ const applyMixinsWithObservables = require('./applyMixinsWithObservables.cjs');
9
9
  const listbox = require('./listbox.cjs');
10
10
  const formAssociated = require('./form-associated.cjs');
11
11
  const affix = require('./affix.cjs');
@@ -19,7 +19,7 @@ const slotted = require('./slotted.cjs');
19
19
  const when = require('./when.cjs');
20
20
  const classNames = require('./class-names.cjs');
21
21
 
22
- const styles = ".chevron{display:flex;flex-shrink:0;font:var(--vvd-typography-base-extended);transform:rotate(0);transition:transform .2s}:host([aria-expanded=true]) .chevron,:host([open]) .chevron{transform:rotate(180deg)}:host{position:relative}.base{--_text-field-gutter-end: 8px}.base{--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-intermediate)}.base.appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-fierce)}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)).appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: var(--_connotation-color-faint);--_appearance-color-outline: transparent}.base:where(.disabled,:disabled){--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: var(--vvd-color-neutral-100);--_appearance-color-outline: var(--vvd-color-neutral-300)}.base:where(.disabled,:disabled).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.readonly):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-neutral-200);--_appearance-color-outline: var(--vvd-color-neutral-400)}.base:where(.readonly):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-600);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.error):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: var(--vvd-color-alert-500)}.base:where(.error):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: transparent}.base:where(.success):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: var(--vvd-color-success-500)}.base:where(.success):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: transparent}.base:not(.shape-pill) .base{border-radius:var(--_text-field-border-radius)}.base.shape-pill .base{border-radius:var(--_text-field-pill-border-radius)}.base slot[name=icon]{position:absolute;z-index:1;display:inline-block;color:var(--_low-ink-color);font-size:var(--_text-field-icon-size);inset-block-start:50%;inset-inline-start:var(--_text-field-gutter-start);line-height:1;pointer-events:none;transform:translateY(-50%)}.base.has-meta{padding-inline-end:16px}.control{text-overflow:ellipsis;white-space:nowrap}.fieldset .leading-items-wrapper{position:relative;display:flex;flex-shrink:0;align-items:center;gap:8px;padding-inline-end:16px}:not(.disabled) .chevron{cursor:pointer}.disabled .chevron{color:var(--_low-ink-color);cursor:not-allowed}.listbox{display:flex;max-height:var(--combobox-height, 408px);flex-direction:column;padding:4px;border-radius:8px;contain:paint;gap:2px;overflow-y:auto}::part(popup-base){inline-size:max-content;min-inline-size:var(--_combobox-fixed-width, 100%)}@supports selector(:has(*)){.fieldset:has(.control:focus-within):after{--focus-stroke-gap-color: transparent;box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px))}}@supports not selector(:has(*)){.fieldset:focus-within:after{box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px));--focus-stroke-gap-color: transparent;position:absolute;z-index:1;display:block;border-radius:inherit;content:\"\";inset:0;pointer-events:none}}";
22
+ const styles = ".chevron{display:flex;flex-shrink:0;font:var(--vvd-typography-base-extended);transform:rotate(0);transition:transform .2s}:host([aria-expanded=true]) .chevron,:host([open]) .chevron{transform:rotate(180deg)}:host{position:relative;display:inline-flex;flex-direction:column;gap:4px}.base{--_text-field-gutter-end: 8px}.base{--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-intermediate)}.base.appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-fierce)}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)).appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: var(--_connotation-color-faint);--_appearance-color-outline: transparent}.base:where(.disabled,:disabled){--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: var(--vvd-color-neutral-100);--_appearance-color-outline: var(--vvd-color-neutral-300)}.base:where(.disabled,:disabled).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.readonly):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-neutral-200);--_appearance-color-outline: var(--vvd-color-neutral-400)}.base:where(.readonly):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-600);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.error):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: var(--vvd-color-alert-500)}.base:where(.error):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: transparent}.base:where(.success):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: var(--vvd-color-success-500)}.base:where(.success):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: transparent}.base:not(.shape-pill) .base{border-radius:var(--_text-field-border-radius)}.base.shape-pill .base{border-radius:var(--_text-field-pill-border-radius)}.base slot[name=icon]{position:absolute;z-index:1;display:inline-block;color:var(--_low-ink-color);font-size:var(--_text-field-icon-size);inset-block-start:50%;inset-inline-start:var(--_text-field-gutter-start);line-height:1;pointer-events:none;transform:translateY(-50%)}.base.has-meta{padding-inline-end:16px}.control{text-overflow:ellipsis;white-space:nowrap}.fieldset .leading-items-wrapper{position:relative;display:flex;flex-shrink:0;align-items:center;gap:8px;padding-inline-end:16px}:not(.disabled) .chevron{cursor:pointer}.disabled .chevron{color:var(--_low-ink-color);cursor:not-allowed}.listbox{display:flex;max-height:var(--combobox-height, 408px);flex-direction:column;padding:4px;border-radius:8px;contain:paint;gap:2px;overflow-y:auto}::part(popup-base){inline-size:max-content;min-inline-size:var(--_combobox-fixed-width, 100%)}@supports selector(:has(*)){.fieldset:has(.control:focus-within):after{--focus-stroke-gap-color: transparent;box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px))}}@supports not selector(:has(*)){.fieldset:focus-within:after{box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px));--focus-stroke-gap-color: transparent;position:absolute;z-index:1;display:block;border-radius:inherit;content:\"\";inset:0;pointer-events:none}}";
23
23
 
24
24
  class _Combobox extends listbox.Listbox {
25
25
  }
@@ -542,14 +542,22 @@ __decorateClass([
542
542
  vividElement.attr
543
543
  ], Combobox.prototype, "placeholder", 2);
544
544
  Combobox = __decorateClass([
545
+ formElements.errorText,
545
546
  formElements.formElements
546
547
  ], Combobox);
547
- applyMixins.applyMixins(Combobox, affix.AffixIcon);
548
+ applyMixinsWithObservables.applyMixinsWithObservables(
549
+ Combobox,
550
+ affix.AffixIcon,
551
+ formElements.FormElementHelperText,
552
+ formElements.FormElementSuccessText
553
+ );
548
554
 
549
555
  const getStateClasses = ({
550
556
  icon,
551
557
  iconSlottedContent,
552
558
  metaSlottedContent,
559
+ errorValidationMessage,
560
+ successText,
553
561
  shape,
554
562
  scale,
555
563
  disabled,
@@ -565,7 +573,9 @@ const getStateClasses = ({
565
573
  [`appearance-${appearance}`, Boolean(appearance)],
566
574
  ["no-label", !label],
567
575
  ["has-icon", !!icon || Boolean(iconSlottedContent?.length)],
568
- ["has-meta", Boolean(metaSlottedContent?.length)]
576
+ ["has-meta", Boolean(metaSlottedContent?.length)],
577
+ ["error", Boolean(errorValidationMessage)],
578
+ ["success", !!successText]
569
579
  );
570
580
  function renderLabel() {
571
581
  return vividElement.html` <label for="control" class="label">
@@ -645,6 +655,9 @@ const comboboxTemplate = (context) => {
645
655
  </slot>
646
656
  </div>
647
657
  </${popupTag}>
658
+ <div class="feedback-wrapper" @click="${(_, c) => c.event.stopPropagation()}">
659
+ ${formElements.getFeedbackTemplate(context)}
660
+ </div>
648
661
  </template>
649
662
  `;
650
663
  };
@@ -3,13 +3,13 @@ import { P as Popup, p as popupDefinition } from './definition63.js';
3
3
  import { l as listboxOptionDefinition } from './definition35.js';
4
4
  import { s as styles$1 } from './text-field.js';
5
5
  import { D as DOM, O as Observable, a as attr, o as observable, h as html, d as defineVividComponent, f as createRegisterFunction } from './vivid-element.js';
6
- import { a as applyMixins } from './apply-mixins.js';
6
+ import { a as applyMixinsWithObservables } from './applyMixinsWithObservables.js';
7
7
  import { L as Listbox } from './listbox.js';
8
8
  import { F as FormAssociated } from './form-associated.js';
9
9
  import { b as AffixIcon, a as affixIconTemplateFactory, I as IconWrapper } from './affix.js';
10
10
  import { u as uniqueId } from './strings.js';
11
11
  import { l as limit } from './numbers.js';
12
- import { f as formElements } from './form-elements.js';
12
+ import { e as errorText, f as formElements, F as FormElementSuccessText, a as FormElementHelperText, g as getFeedbackTemplate } from './form-elements.js';
13
13
  import { h as handleEscapeKeyAndStopPropogation } from './index.js';
14
14
  import { c as chevronTemplateFactory } from './definition11.js';
15
15
  import { r as ref } from './ref.js';
@@ -17,7 +17,7 @@ import { s as slotted } from './slotted.js';
17
17
  import { w as when } from './when.js';
18
18
  import { c as classNames } from './class-names.js';
19
19
 
20
- const styles = ".chevron{display:flex;flex-shrink:0;font:var(--vvd-typography-base-extended);transform:rotate(0);transition:transform .2s}:host([aria-expanded=true]) .chevron,:host([open]) .chevron{transform:rotate(180deg)}:host{position:relative}.base{--_text-field-gutter-end: 8px}.base{--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-intermediate)}.base.appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-fierce)}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)).appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: var(--_connotation-color-faint);--_appearance-color-outline: transparent}.base:where(.disabled,:disabled){--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: var(--vvd-color-neutral-100);--_appearance-color-outline: var(--vvd-color-neutral-300)}.base:where(.disabled,:disabled).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.readonly):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-neutral-200);--_appearance-color-outline: var(--vvd-color-neutral-400)}.base:where(.readonly):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-600);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.error):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: var(--vvd-color-alert-500)}.base:where(.error):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: transparent}.base:where(.success):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: var(--vvd-color-success-500)}.base:where(.success):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: transparent}.base:not(.shape-pill) .base{border-radius:var(--_text-field-border-radius)}.base.shape-pill .base{border-radius:var(--_text-field-pill-border-radius)}.base slot[name=icon]{position:absolute;z-index:1;display:inline-block;color:var(--_low-ink-color);font-size:var(--_text-field-icon-size);inset-block-start:50%;inset-inline-start:var(--_text-field-gutter-start);line-height:1;pointer-events:none;transform:translateY(-50%)}.base.has-meta{padding-inline-end:16px}.control{text-overflow:ellipsis;white-space:nowrap}.fieldset .leading-items-wrapper{position:relative;display:flex;flex-shrink:0;align-items:center;gap:8px;padding-inline-end:16px}:not(.disabled) .chevron{cursor:pointer}.disabled .chevron{color:var(--_low-ink-color);cursor:not-allowed}.listbox{display:flex;max-height:var(--combobox-height, 408px);flex-direction:column;padding:4px;border-radius:8px;contain:paint;gap:2px;overflow-y:auto}::part(popup-base){inline-size:max-content;min-inline-size:var(--_combobox-fixed-width, 100%)}@supports selector(:has(*)){.fieldset:has(.control:focus-within):after{--focus-stroke-gap-color: transparent;box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px))}}@supports not selector(:has(*)){.fieldset:focus-within:after{box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px));--focus-stroke-gap-color: transparent;position:absolute;z-index:1;display:block;border-radius:inherit;content:\"\";inset:0;pointer-events:none}}";
20
+ const styles = ".chevron{display:flex;flex-shrink:0;font:var(--vvd-typography-base-extended);transform:rotate(0);transition:transform .2s}:host([aria-expanded=true]) .chevron,:host([open]) .chevron{transform:rotate(180deg)}:host{position:relative;display:inline-flex;flex-direction:column;gap:4px}.base{--_text-field-gutter-end: 8px}.base{--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-intermediate)}.base.appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--_connotation-color-fierce)}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)).appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: var(--_connotation-color-faint);--_appearance-color-outline: transparent}.base:where(.disabled,:disabled){--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: var(--vvd-color-neutral-100);--_appearance-color-outline: var(--vvd-color-neutral-300)}.base:where(.disabled,:disabled).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.readonly):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-neutral-200);--_appearance-color-outline: var(--vvd-color-neutral-400)}.base:where(.readonly):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-600);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.base:where(.error):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: var(--vvd-color-alert-500)}.base:where(.error):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: transparent}.base:where(.success):where(:not(.disabled,:disabled)){--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: var(--vvd-color-success-500)}.base:where(.success):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: transparent}.base:not(.shape-pill) .base{border-radius:var(--_text-field-border-radius)}.base.shape-pill .base{border-radius:var(--_text-field-pill-border-radius)}.base slot[name=icon]{position:absolute;z-index:1;display:inline-block;color:var(--_low-ink-color);font-size:var(--_text-field-icon-size);inset-block-start:50%;inset-inline-start:var(--_text-field-gutter-start);line-height:1;pointer-events:none;transform:translateY(-50%)}.base.has-meta{padding-inline-end:16px}.control{text-overflow:ellipsis;white-space:nowrap}.fieldset .leading-items-wrapper{position:relative;display:flex;flex-shrink:0;align-items:center;gap:8px;padding-inline-end:16px}:not(.disabled) .chevron{cursor:pointer}.disabled .chevron{color:var(--_low-ink-color);cursor:not-allowed}.listbox{display:flex;max-height:var(--combobox-height, 408px);flex-direction:column;padding:4px;border-radius:8px;contain:paint;gap:2px;overflow-y:auto}::part(popup-base){inline-size:max-content;min-inline-size:var(--_combobox-fixed-width, 100%)}@supports selector(:has(*)){.fieldset:has(.control:focus-within):after{--focus-stroke-gap-color: transparent;box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px))}}@supports not selector(:has(*)){.fieldset:focus-within:after{box-shadow:inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:2px solid var(--focus-stroke-color, var(--vvd-color-canvas-text));outline-offset:calc(-2px - var(--focus-inset, 0px));--focus-stroke-gap-color: transparent;position:absolute;z-index:1;display:block;border-radius:inherit;content:\"\";inset:0;pointer-events:none}}";
21
21
 
22
22
  class _Combobox extends Listbox {
23
23
  }
@@ -540,14 +540,22 @@ __decorateClass([
540
540
  attr
541
541
  ], Combobox.prototype, "placeholder", 2);
542
542
  Combobox = __decorateClass([
543
+ errorText,
543
544
  formElements
544
545
  ], Combobox);
545
- applyMixins(Combobox, AffixIcon);
546
+ applyMixinsWithObservables(
547
+ Combobox,
548
+ AffixIcon,
549
+ FormElementHelperText,
550
+ FormElementSuccessText
551
+ );
546
552
 
547
553
  const getStateClasses = ({
548
554
  icon,
549
555
  iconSlottedContent,
550
556
  metaSlottedContent,
557
+ errorValidationMessage,
558
+ successText,
551
559
  shape,
552
560
  scale,
553
561
  disabled,
@@ -563,7 +571,9 @@ const getStateClasses = ({
563
571
  [`appearance-${appearance}`, Boolean(appearance)],
564
572
  ["no-label", !label],
565
573
  ["has-icon", !!icon || Boolean(iconSlottedContent?.length)],
566
- ["has-meta", Boolean(metaSlottedContent?.length)]
574
+ ["has-meta", Boolean(metaSlottedContent?.length)],
575
+ ["error", Boolean(errorValidationMessage)],
576
+ ["success", !!successText]
567
577
  );
568
578
  function renderLabel() {
569
579
  return html` <label for="control" class="label">
@@ -643,6 +653,9 @@ const comboboxTemplate = (context) => {
643
653
  </slot>
644
654
  </div>
645
655
  </${popupTag}>
656
+ <div class="feedback-wrapper" @click="${(_, c) => c.event.stopPropagation()}">
657
+ ${getFeedbackTemplate(context)}
658
+ </div>
646
659
  </template>
647
660
  `;
648
661
  };
@@ -536,11 +536,8 @@ const _DataGrid = class _DataGrid extends vividElement.VividElement {
536
536
  this.generatedHeader.columnDefinitions = this.columnDefinitions;
537
537
  this.generatedHeader.gridTemplateColumns = this.gridTemplateColumns;
538
538
  this.generatedHeader.rowType = this.generateHeader === GenerateHeaderOptions.sticky ? DataGridRowTypes.stickyHeader : DataGridRowTypes.header;
539
- if (this.firstChild !== null || this.rowsPlaceholder !== null) {
540
- this.insertBefore(
541
- generatedHeaderElement,
542
- this.firstChild !== null ? this.firstChild : this.rowsPlaceholder
543
- );
539
+ if (this.firstChild !== null) {
540
+ this.insertBefore(generatedHeaderElement, this.firstChild);
544
541
  }
545
542
  return;
546
543
  }
@@ -534,11 +534,8 @@ const _DataGrid = class _DataGrid extends VividElement {
534
534
  this.generatedHeader.columnDefinitions = this.columnDefinitions;
535
535
  this.generatedHeader.gridTemplateColumns = this.gridTemplateColumns;
536
536
  this.generatedHeader.rowType = this.generateHeader === GenerateHeaderOptions.sticky ? DataGridRowTypes.stickyHeader : DataGridRowTypes.header;
537
- if (this.firstChild !== null || this.rowsPlaceholder !== null) {
538
- this.insertBefore(
539
- generatedHeaderElement,
540
- this.firstChild !== null ? this.firstChild : this.rowsPlaceholder
541
- );
537
+ if (this.firstChild !== null) {
538
+ this.insertBefore(generatedHeaderElement, this.firstChild);
542
539
  }
543
540
  return;
544
541
  }
@@ -145,7 +145,7 @@ _has._curry2(function memoizeWith(mFn, fn) {
145
145
  });
146
146
 
147
147
  const ICONS_BASE_URL = "https://icon.resources.vonage.com";
148
- const ICONS_VERSION = "4.6.3";
148
+ const ICONS_VERSION = "4.6.4";
149
149
 
150
150
  const numberConverter = {
151
151
  toView(value) {
@@ -143,7 +143,7 @@ _curry2(function memoizeWith(mFn, fn) {
143
143
  });
144
144
 
145
145
  const ICONS_BASE_URL = "https://icon.resources.vonage.com";
146
- const ICONS_VERSION = "4.6.3";
146
+ const ICONS_VERSION = "4.6.4";
147
147
 
148
148
  const numberConverter = {
149
149
  toView(value) {
@@ -75,6 +75,7 @@ const NavDisclosureTemplate = (context) => {
75
75
  const iconTag = context.tagFor(definition.Icon);
76
76
  return vividElement.html`<details class="base" ${ref.ref("details")} ?open=${(x) => x.open}>
77
77
  <summary class="${getClasses}"
78
+ aria-label=${(x) => x.label ? x.label : "Toggle"}
78
79
  role="button"
79
80
  aria-controls="disclosure-content"
80
81
  aria-expanded="${(x) => x.open}"
@@ -73,6 +73,7 @@ const NavDisclosureTemplate = (context) => {
73
73
  const iconTag = context.tagFor(Icon);
74
74
  return html`<details class="base" ${ref("details")} ?open=${(x) => x.open}>
75
75
  <summary class="${getClasses}"
76
+ aria-label=${(x) => x.label ? x.label : "Toggle"}
76
77
  role="button"
77
78
  aria-controls="disclosure-content"
78
79
  aria-expanded="${(x) => x.open}"
@@ -483,7 +483,7 @@ __decorateClass([
483
483
  vividElement.attr({ converter: vividElement.nullableNumberConverter })
484
484
  ], RangeSlider.prototype, "max", 2);
485
485
  __decorateClass([
486
- vividElement.attr({ converter: vividElement.nullableNumberConverter })
486
+ vividElement.attr({ converter: slider_template.defaultToOneConverter })
487
487
  ], RangeSlider.prototype, "step", 2);
488
488
  __decorateClass([
489
489
  vividElement.attr
@@ -3,7 +3,7 @@ import { V as VividElement, o as observable, a as attr, n as nullableNumberConve
3
3
  import { g as keyHome, d as keyEnd, e as keyArrowUp, h as keyArrowLeft, f as keyArrowDown, i as keyArrowRight } from './key-codes.js';
4
4
  import { a as applyMixins } from './apply-mixins.js';
5
5
  import { F as FormAssociated } from './form-associated.js';
6
- import { i as inverseLerp, l as lerp, r as roundToStepValue, g as getMarkersTemplate } from './slider.template.js';
6
+ import { i as inverseLerp, l as lerp, r as roundToStepValue, d as defaultToOneConverter, g as getMarkersTemplate } from './slider.template.js';
7
7
  import { O as Orientation } from './aria.js';
8
8
  import { l as limit } from './numbers.js';
9
9
  import { f as formElements } from './form-elements.js';
@@ -481,7 +481,7 @@ __decorateClass([
481
481
  attr({ converter: nullableNumberConverter })
482
482
  ], RangeSlider.prototype, "max", 2);
483
483
  __decorateClass([
484
- attr({ converter: nullableNumberConverter })
484
+ attr({ converter: defaultToOneConverter })
485
485
  ], RangeSlider.prototype, "step", 2);
486
486
  __decorateClass([
487
487
  attr
@@ -150,12 +150,12 @@ let Select = class extends FormAssociatedSelect {
150
150
  this.rangeStartIndex = this.activeIndex;
151
151
  }
152
152
  this.options.forEach((o, i) => {
153
- o.checked = numbers.inRange(i, this.rangeStartIndex, this.options.length);
153
+ o.checked = numbers.inRange(i, this.rangeStartIndex, this.length);
154
154
  });
155
155
  } else {
156
156
  this.uncheckAllOptions();
157
157
  }
158
- this.activeIndex = this.options.length - 1;
158
+ this.activeIndex = this.length - 1;
159
159
  this.checkActiveIndex();
160
160
  }
161
161
  /**
@@ -179,7 +179,7 @@ let Select = class extends FormAssociatedSelect {
179
179
  } else {
180
180
  this.uncheckAllOptions();
181
181
  }
182
- this.activeIndex += this.activeIndex < this.options.length - 1 ? 1 : 0;
182
+ this.activeIndex += this.activeIndex < this.length - 1 ? 1 : 0;
183
183
  this.checkActiveIndex();
184
184
  }
185
185
  /**
@@ -346,7 +346,7 @@ let Select = class extends FormAssociatedSelect {
346
346
  }
347
347
  set value(next) {
348
348
  const prev = `${this._value}`;
349
- if (this._options.length) {
349
+ if (this.length) {
350
350
  const selectedIndex = this._options.findIndex((el) => el.value === next);
351
351
  const prevSelectedValue = this._options[this.selectedIndex]?.value ?? null;
352
352
  const nextSelectedValue = this._options[selectedIndex]?.value ?? null;
@@ -523,7 +523,7 @@ let Select = class extends FormAssociatedSelect {
523
523
  */
524
524
  setProxyOptions() {
525
525
  if (this.proxy instanceof HTMLSelectElement && this.options) {
526
- this.proxy.options.length = 0;
526
+ this.proxy.length = 0;
527
527
  this.options.forEach((option) => {
528
528
  const proxyOption = option.proxy || (option instanceof HTMLOptionElement ? option.cloneNode() : null);
529
529
  if (proxyOption) {
@@ -148,12 +148,12 @@ let Select = class extends FormAssociatedSelect {
148
148
  this.rangeStartIndex = this.activeIndex;
149
149
  }
150
150
  this.options.forEach((o, i) => {
151
- o.checked = inRange(i, this.rangeStartIndex, this.options.length);
151
+ o.checked = inRange(i, this.rangeStartIndex, this.length);
152
152
  });
153
153
  } else {
154
154
  this.uncheckAllOptions();
155
155
  }
156
- this.activeIndex = this.options.length - 1;
156
+ this.activeIndex = this.length - 1;
157
157
  this.checkActiveIndex();
158
158
  }
159
159
  /**
@@ -177,7 +177,7 @@ let Select = class extends FormAssociatedSelect {
177
177
  } else {
178
178
  this.uncheckAllOptions();
179
179
  }
180
- this.activeIndex += this.activeIndex < this.options.length - 1 ? 1 : 0;
180
+ this.activeIndex += this.activeIndex < this.length - 1 ? 1 : 0;
181
181
  this.checkActiveIndex();
182
182
  }
183
183
  /**
@@ -344,7 +344,7 @@ let Select = class extends FormAssociatedSelect {
344
344
  }
345
345
  set value(next) {
346
346
  const prev = `${this._value}`;
347
- if (this._options.length) {
347
+ if (this.length) {
348
348
  const selectedIndex = this._options.findIndex((el) => el.value === next);
349
349
  const prevSelectedValue = this._options[this.selectedIndex]?.value ?? null;
350
350
  const nextSelectedValue = this._options[selectedIndex]?.value ?? null;
@@ -521,7 +521,7 @@ let Select = class extends FormAssociatedSelect {
521
521
  */
522
522
  setProxyOptions() {
523
523
  if (this.proxy instanceof HTMLSelectElement && this.options) {
524
- this.proxy.options.length = 0;
524
+ this.proxy.length = 0;
525
525
  this.options.forEach((option) => {
526
526
  const proxyOption = option.proxy || (option instanceof HTMLOptionElement ? option.cloneNode() : null);
527
527
  if (proxyOption) {
@@ -449,7 +449,7 @@ __decorateClass([
449
449
  vividElement.attr({ converter: vividElement.nullableNumberConverter })
450
450
  ], Slider.prototype, "max", 2);
451
451
  __decorateClass([
452
- vividElement.attr({ converter: vividElement.nullableNumberConverter })
452
+ vividElement.attr({ converter: slider_template.defaultToOneConverter })
453
453
  ], Slider.prototype, "step", 2);
454
454
  __decorateClass([
455
455
  vividElement.attr
@@ -3,7 +3,7 @@ import { V as VividElement, a as attr, o as observable, v as volatile, n as null
3
3
  import { g as keyHome, d as keyEnd, f as keyArrowDown, h as keyArrowLeft, e as keyArrowUp, i as keyArrowRight } from './key-codes.js';
4
4
  import { D as Direction, g as getDirection } from './direction.js';
5
5
  import { a as applyMixins } from './apply-mixins.js';
6
- import { i as inverseLerp, l as lerp, r as roundToStepValue, S as SliderTemplate } from './slider.template.js';
6
+ import { i as inverseLerp, l as lerp, r as roundToStepValue, d as defaultToOneConverter, S as SliderTemplate } from './slider.template.js';
7
7
  import { F as FormAssociated } from './form-associated.js';
8
8
  import { O as Orientation } from './aria.js';
9
9
  import { l as limit } from './numbers.js';
@@ -447,7 +447,7 @@ __decorateClass([
447
447
  attr({ converter: nullableNumberConverter })
448
448
  ], Slider.prototype, "max", 2);
449
449
  __decorateClass([
450
- attr({ converter: nullableNumberConverter })
450
+ attr({ converter: defaultToOneConverter })
451
451
  ], Slider.prototype, "step", 2);
452
452
  __decorateClass([
453
453
  attr
@@ -95,6 +95,7 @@ class Tabs extends vividElement.VividElement {
95
95
  tab.style[gridProperty] = `${index + 1}`;
96
96
  !this.#isHorizontal() ? tab.classList.add("vertical") : tab.classList.remove("vertical");
97
97
  });
98
+ this.#updateTabsConnotation();
98
99
  };
99
100
  this.setTabPanels = () => {
100
101
  this.tabpanels.forEach((tabpanel, index) => {
@@ -196,7 +197,6 @@ class Tabs extends vividElement.VividElement {
196
197
  this.#handleActiveIndicatorPosition();
197
198
  }
198
199
  this.#patchIndicatorStyleTransition();
199
- this.#updateTabsConnotation();
200
200
  this.#scrollToIndex(this.activeTabIndex);
201
201
  }
202
202
  #isLastTabSelectedAfterRemove;
@@ -93,6 +93,7 @@ class Tabs extends VividElement {
93
93
  tab.style[gridProperty] = `${index + 1}`;
94
94
  !this.#isHorizontal() ? tab.classList.add("vertical") : tab.classList.remove("vertical");
95
95
  });
96
+ this.#updateTabsConnotation();
96
97
  };
97
98
  this.setTabPanels = () => {
98
99
  this.tabpanels.forEach((tabpanel, index) => {
@@ -194,7 +195,6 @@ class Tabs extends VividElement {
194
195
  this.#handleActiveIndicatorPosition();
195
196
  }
196
197
  this.#patchIndicatorStyleTransition();
197
- this.#updateTabsConnotation();
198
198
  this.#scrollToIndex(this.activeTabIndex);
199
199
  }
200
200
  #isLastTabSelectedAfterRemove;
@@ -1105,7 +1105,8 @@ function isContainingBlock(elementOrCss) {
1105
1105
  const css = isElement(elementOrCss) ? getComputedStyle(elementOrCss) : elementOrCss;
1106
1106
 
1107
1107
  // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
1108
- return css.transform !== 'none' || css.perspective !== 'none' || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value));
1108
+ // https://drafts.csswg.org/css-transforms-2/#individual-transforms
1109
+ return ['transform', 'translate', 'scale', 'rotate', 'perspective'].some(value => css[value] ? css[value] !== 'none' : false) || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'translate', 'scale', 'rotate', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value));
1109
1110
  }
1110
1111
  function getContainingBlock(element) {
1111
1112
  let currentNode = getParentNode(element);
@@ -1663,6 +1664,10 @@ const platform = {
1663
1664
  isRTL
1664
1665
  };
1665
1666
 
1667
+ function rectsAreEqual(a, b) {
1668
+ return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
1669
+ }
1670
+
1666
1671
  // https://samthor.au/2021/observing-dom/
1667
1672
  function observeMove(element, onMove) {
1668
1673
  let io = null;
@@ -1682,12 +1687,13 @@ function observeMove(element, onMove) {
1682
1687
  threshold = 1;
1683
1688
  }
1684
1689
  cleanup();
1690
+ const elementRectForRootMargin = element.getBoundingClientRect();
1685
1691
  const {
1686
1692
  left,
1687
1693
  top,
1688
1694
  width,
1689
1695
  height
1690
- } = element.getBoundingClientRect();
1696
+ } = elementRectForRootMargin;
1691
1697
  if (!skip) {
1692
1698
  onMove();
1693
1699
  }
@@ -1720,6 +1726,16 @@ function observeMove(element, onMove) {
1720
1726
  refresh(false, ratio);
1721
1727
  }
1722
1728
  }
1729
+ if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
1730
+ // It's possible that even though the ratio is reported as 1, the
1731
+ // element is not actually fully within the IntersectionObserver's root
1732
+ // area anymore. This can happen under performance constraints. This may
1733
+ // be a bug in the browser's IntersectionObserver implementation. To
1734
+ // work around this, we compare the element's bounding rect now with
1735
+ // what it was at the time we created the IntersectionObserver. If they
1736
+ // are not equal then the element moved, so we refresh.
1737
+ refresh();
1738
+ }
1723
1739
  isFirstUpdate = false;
1724
1740
  }
1725
1741
 
@@ -1797,7 +1813,7 @@ function autoUpdate(reference, floating, update, options) {
1797
1813
  }
1798
1814
  function frameLoop() {
1799
1815
  const nextRefRect = getBoundingClientRect(reference);
1800
- if (prevRefRect && (nextRefRect.x !== prevRefRect.x || nextRefRect.y !== prevRefRect.y || nextRefRect.width !== prevRefRect.width || nextRefRect.height !== prevRefRect.height)) {
1816
+ if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) {
1801
1817
  update();
1802
1818
  }
1803
1819
  prevRefRect = nextRefRect;
@@ -1103,7 +1103,8 @@ function isContainingBlock(elementOrCss) {
1103
1103
  const css = isElement(elementOrCss) ? getComputedStyle(elementOrCss) : elementOrCss;
1104
1104
 
1105
1105
  // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
1106
- return css.transform !== 'none' || css.perspective !== 'none' || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value));
1106
+ // https://drafts.csswg.org/css-transforms-2/#individual-transforms
1107
+ return ['transform', 'translate', 'scale', 'rotate', 'perspective'].some(value => css[value] ? css[value] !== 'none' : false) || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'translate', 'scale', 'rotate', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value));
1107
1108
  }
1108
1109
  function getContainingBlock(element) {
1109
1110
  let currentNode = getParentNode(element);
@@ -1661,6 +1662,10 @@ const platform = {
1661
1662
  isRTL
1662
1663
  };
1663
1664
 
1665
+ function rectsAreEqual(a, b) {
1666
+ return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
1667
+ }
1668
+
1664
1669
  // https://samthor.au/2021/observing-dom/
1665
1670
  function observeMove(element, onMove) {
1666
1671
  let io = null;
@@ -1680,12 +1685,13 @@ function observeMove(element, onMove) {
1680
1685
  threshold = 1;
1681
1686
  }
1682
1687
  cleanup();
1688
+ const elementRectForRootMargin = element.getBoundingClientRect();
1683
1689
  const {
1684
1690
  left,
1685
1691
  top,
1686
1692
  width,
1687
1693
  height
1688
- } = element.getBoundingClientRect();
1694
+ } = elementRectForRootMargin;
1689
1695
  if (!skip) {
1690
1696
  onMove();
1691
1697
  }
@@ -1718,6 +1724,16 @@ function observeMove(element, onMove) {
1718
1724
  refresh(false, ratio);
1719
1725
  }
1720
1726
  }
1727
+ if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
1728
+ // It's possible that even though the ratio is reported as 1, the
1729
+ // element is not actually fully within the IntersectionObserver's root
1730
+ // area anymore. This can happen under performance constraints. This may
1731
+ // be a bug in the browser's IntersectionObserver implementation. To
1732
+ // work around this, we compare the element's bounding rect now with
1733
+ // what it was at the time we created the IntersectionObserver. If they
1734
+ // are not equal then the element moved, so we refresh.
1735
+ refresh();
1736
+ }
1721
1737
  isFirstUpdate = false;
1722
1738
  }
1723
1739
 
@@ -1795,7 +1811,7 @@ function autoUpdate(reference, floating, update, options) {
1795
1811
  }
1796
1812
  function frameLoop() {
1797
1813
  const nextRefRect = getBoundingClientRect(reference);
1798
- if (prevRefRect && (nextRefRect.x !== prevRefRect.x || nextRefRect.y !== prevRefRect.y || nextRefRect.width !== prevRefRect.width || nextRefRect.height !== prevRefRect.height)) {
1814
+ if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) {
1799
1815
  update();
1800
1816
  }
1801
1817
  prevRefRect = nextRefRect;
@@ -6172,10 +6172,11 @@ class DatePickerBase extends FormAssociatedDatePickerBase {
6172
6172
  } else {
6173
6173
  this.#openPopupIfPossible();
6174
6174
  vividElement.DOM.processUpdates();
6175
- const tabbableDate = this.shadowRoot.querySelector(
6176
- `[data-date="${this._tabbableDate}"]`
6177
- );
6178
- tabbableDate.focus();
6175
+ const tabbableDate = this._tabbableDate;
6176
+ if (tabbableDate)
6177
+ this.shadowRoot.querySelector(
6178
+ `[data-date="${tabbableDate}"]`
6179
+ ).focus();
6179
6180
  }
6180
6181
  }
6181
6182
  // --- Dialog header ---
@@ -6170,10 +6170,11 @@ class DatePickerBase extends FormAssociatedDatePickerBase {
6170
6170
  } else {
6171
6171
  this.#openPopupIfPossible();
6172
6172
  DOM.processUpdates();
6173
- const tabbableDate = this.shadowRoot.querySelector(
6174
- `[data-date="${this._tabbableDate}"]`
6175
- );
6176
- tabbableDate.focus();
6173
+ const tabbableDate = this._tabbableDate;
6174
+ if (tabbableDate)
6175
+ this.shadowRoot.querySelector(
6176
+ `[data-date="${tabbableDate}"]`
6177
+ ).focus();
6177
6178
  }
6178
6179
  }
6179
6180
  // --- Dialog header ---