@vonage/vivid 4.28.0 → 4.30.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.
Files changed (92) hide show
  1. package/custom-elements.json +707 -86
  2. package/lib/accordion-item/accordion-item.d.ts +3 -1
  3. package/lib/audio-player/audio-player.d.ts +4 -3
  4. package/lib/data-grid/data-grid.d.ts +2 -0
  5. package/lib/data-grid/locale.d.ts +1 -0
  6. package/lib/date-picker/date-picker.d.ts +4 -2
  7. package/lib/date-time-picker/date-time-picker.d.ts +6 -3
  8. package/lib/divider/definition.d.ts +1 -0
  9. package/lib/divider/divider.d.ts +5 -1
  10. package/lib/option/option.d.ts +4 -7
  11. package/lib/rich-text-editor/facades/prose-mirror-vivid.schema.d.ts +2 -1
  12. package/lib/rich-text-editor/facades/vivid-prose-mirror.facade.d.ts +2 -2
  13. package/lib/rich-text-editor/image-placeholder/definition.d.ts +2 -0
  14. package/lib/rich-text-editor/image-placeholder/image-placeholder.d.ts +7 -0
  15. package/lib/rich-text-editor/image-placeholder/image-placeholder.template.d.ts +4 -0
  16. package/lib/rich-text-editor/menubar/consts.d.ts +2 -2
  17. package/lib/rich-text-editor/menubar/definition.d.ts +2 -2
  18. package/lib/rich-text-editor/menubar/menubar.d.ts +2 -2
  19. package/lib/rich-text-editor/menubar/menubar.template.d.ts +2 -2
  20. package/lib/rich-text-editor/rich-text-editor.d.ts +1 -0
  21. package/lib/selectable-box/selectable-box.d.ts +2 -0
  22. package/lib/split-button/split-button.d.ts +1 -1
  23. package/lib/tag/tag.d.ts +1 -1
  24. package/lib/time-picker/time-picker.d.ts +4 -2
  25. package/locales/de-DE.cjs +2 -1
  26. package/locales/de-DE.js +2 -1
  27. package/locales/en-GB.cjs +2 -1
  28. package/locales/en-GB.js +2 -1
  29. package/locales/en-US.cjs +2 -1
  30. package/locales/en-US.js +2 -1
  31. package/locales/ja-JP.cjs +2 -1
  32. package/locales/ja-JP.js +2 -1
  33. package/locales/zh-CN.cjs +2 -1
  34. package/locales/zh-CN.js +2 -1
  35. package/package.json +2 -1
  36. package/shared/calendar-picker.template.cjs +6 -5
  37. package/shared/calendar-picker.template.js +6 -5
  38. package/shared/definition.cjs +11 -2
  39. package/shared/definition.js +11 -2
  40. package/shared/definition16.cjs +33 -30
  41. package/shared/definition16.js +33 -30
  42. package/shared/definition17.cjs +137 -1
  43. package/shared/definition17.js +138 -2
  44. package/shared/definition23.cjs +12 -7
  45. package/shared/definition23.js +12 -7
  46. package/shared/definition28.cjs +1 -2
  47. package/shared/definition28.js +2 -2
  48. package/shared/definition36.cjs +1 -1
  49. package/shared/definition36.js +1 -1
  50. package/shared/definition44.cjs +194 -77
  51. package/shared/definition44.js +194 -77
  52. package/shared/definition45.cjs +12 -5
  53. package/shared/definition45.js +12 -5
  54. package/shared/definition47.cjs +11 -5
  55. package/shared/definition47.js +11 -5
  56. package/shared/definition5.cjs +86 -30
  57. package/shared/definition5.js +86 -30
  58. package/shared/definition50.cjs +1 -1
  59. package/shared/definition50.js +1 -1
  60. package/shared/definition56.cjs +1 -1
  61. package/shared/definition56.js +1 -1
  62. package/shared/definition58.cjs +10 -29
  63. package/shared/definition58.js +12 -31
  64. package/shared/definition61.cjs +11 -0
  65. package/shared/definition61.js +11 -0
  66. package/shared/definition64.cjs +1 -1
  67. package/shared/definition64.js +1 -1
  68. package/shared/definition67.cjs +27 -16
  69. package/shared/definition67.js +27 -16
  70. package/shared/divider.cjs +7 -2
  71. package/shared/divider.js +7 -2
  72. package/shared/option.cjs +36 -38
  73. package/shared/option.js +37 -39
  74. package/shared/picker-field/mixins/single-date-picker.d.ts +4 -2
  75. package/shared/picker-field/mixins/single-value-picker.d.ts +2 -1
  76. package/shared/picker-field/mixins/time-selection-picker.d.ts +4 -2
  77. package/shared/picker-field/mixins/time-selection-picker.template.d.ts +4 -2
  78. package/shared/single-value-picker.cjs +40 -6
  79. package/shared/single-value-picker.js +40 -6
  80. package/shared/text-field.cjs +1 -1
  81. package/shared/text-field.js +1 -1
  82. package/shared/time-selection-picker.template.cjs +2 -2
  83. package/shared/time-selection-picker.template.js +2 -2
  84. package/shared/vivid-element.cjs +2 -1
  85. package/shared/vivid-element.js +2 -2
  86. package/styles/core/all.css +1 -1
  87. package/styles/core/theme.css +1 -1
  88. package/styles/core/typography.css +1 -1
  89. package/styles/tokens/theme-dark.css +4 -4
  90. package/styles/tokens/theme-light.css +4 -4
  91. package/styles/tokens/vivid-2-compat.css +1 -1
  92. package/vivid.api.json +294 -129
@@ -19,9 +19,9 @@ import { s as slotted } from './slotted.js';
19
19
  import { c as classNames } from './class-names.js';
20
20
  import { r as repeat } from './repeat.js';
21
21
 
22
- const styles = ".chevron{display:flex;flex-shrink:0;font:var(--vvd-typography-base-extended);transform:rotate(0);transition:transform .2s}:host([data-expanded=true]) .chevron,:host([open]) .chevron{transform:rotate(180deg)}:not(.disabled) .chevron{cursor:pointer}.disabled .chevron{color:var(--_low-ink-color);cursor:not-allowed}:host(:focus-visible){outline:none}:host{display:inline-block;inline-size:300px;--_low-ink-color: var(--vvd-color-neutral-600)}:host([disabled]){--_low-ink-color: var(--vvd-color-neutral-400);cursor:not-allowed}.control-wrapper{display:flex;flex-direction:column;gap:4px}.label{color:var(--vvd-color-canvas-text);font:var(--vvd-typography-base)}.selection-count{color:var(--_low-ink-color);font:var(--vvd-typography-base)}.fieldset{--_connotation-color-primary: var(--vvd-searchable-select-accent-primary, var(--vvd-color-canvas-text));--_connotation-color-primary-text: var(--vvd-searchable-select-accent-primary-text, var(--vvd-color-canvas));--_connotation-color-primary-increment: var(--vvd-searchable-select-accent-primary-increment, var(--vvd-color-neutral-800));--_connotation-color-intermediate: var(--vvd-searchable-select-accent-intermediate, var(--vvd-color-neutral-500));--_connotation-color-faint: var(--vvd-searchable-select-accent-faint, var(--vvd-color-neutral-50));--_connotation-color-soft: var(--vvd-searchable-select-accent-soft, var(--vvd-color-neutral-100));--_connotation-color-firm: var(--vvd-searchable-select-accent-firm, var(--vvd-color-canvas-text));--_connotation-color-fierce: var(--vvd-searchable-select-accent-fierce, var(--vvd-color-neutral-700))}.fieldset{--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--vvd-color-neutral-500)}.fieldset.appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.fieldset: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(--vvd-color-neutral-700)}.fieldset: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}.fieldset: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)}.fieldset:where(.disabled,:disabled).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.fieldset: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)}.fieldset:where(.readonly):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-600);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.fieldset: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)}.fieldset:where(.error):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: transparent}.fieldset: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)}.fieldset:where(.success):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: transparent}.fieldset{display:flex;align-items:center;justify-content:space-between;background-color:var(--_appearance-color-fill);box-shadow:inset 0 0 0 1px var(--_appearance-color-outline);color:var(--_appearance-color-text);font:var(--vvd-typography-base);gap:8px;padding-block:8px;padding-inline:16px;transition:box-shadow .2s,background-color .2s}.fieldset:focus-within{box-shadow:0 0 0 4px color-mix(in srgb,var(--vvd-color-cta-500),transparent 85%),inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:1px solid var(--focus-stroke-color, var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset, 0px));--focus-stroke-gap-color: transparent}:host(:not([shape=pill])) .fieldset{border-radius:8px}:host([shape=pill]) .fieldset{border-radius:24px}.popup-wrapper{position:relative}.content-area{display:flex;overflow:hidden;flex:1;flex-direction:column;gap:8px;min-block-size:24px}.tag-row{display:flex;gap:8px;inline-size:100%}.tag-row.contains-only-input:not(:focus-within){display:contents}.tag-wrapper{overflow:hidden}.tag{max-inline-size:100%}input{box-sizing:border-box;flex:1;border:none;background:none;block-size:24px;font:var(--vvd-typography-base);max-inline-size:100%;min-inline-size:min(100px,40%);outline:none}.contains-only-input input:not(:focus){position:absolute;block-size:0;inline-size:0;min-inline-size:0;opacity:0;pointer-events:none}.listbox{display:flex;flex-direction:column;padding:4px;gap:2px;max-block-size:var(--searchable-select-height, 408px);overflow-y:auto}.empty-message{display:flex;align-items:center;justify-content:center;color:var(--vvd-color-neutral-300);font:var(--vvd-typography-base);min-block-size:40px;text-align:center}::part(popup-base){inline-size:max-content;min-inline-size:var(--_searchable-select-fixed-width, 100%)}slot[name=icon]{font-size:20px}.visually-hidden{position:absolute;overflow:hidden;width:1px;height:1px;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}";
22
+ const styles = ".chevron{display:flex;flex-shrink:0;font:var(--vvd-typography-base-extended);transform:rotate(0);transition:transform .2s}:host([data-expanded=true]) .chevron,:host([open]) .chevron{transform:rotate(180deg)}:not(.disabled) .chevron{cursor:pointer}.disabled .chevron{color:var(--_low-ink-color);cursor:not-allowed}:host(:focus-visible){outline:none}:host{display:inline-block;inline-size:300px;--_low-ink-color: var(--vvd-color-neutral-600)}:host([disabled]){--_low-ink-color: var(--vvd-color-neutral-400);cursor:not-allowed}.control-wrapper{display:flex;flex-direction:column;gap:4px}.label{color:var(--vvd-color-canvas-text);font:var(--vvd-typography-base)}.selection-count{color:var(--_low-ink-color);font:var(--vvd-typography-base)}.fieldset{--_connotation-color-primary: var(--vvd-searchable-select-accent-primary, var(--vvd-color-canvas-text));--_connotation-color-primary-text: var(--vvd-searchable-select-accent-primary-text, var(--vvd-color-canvas));--_connotation-color-primary-increment: var(--vvd-searchable-select-accent-primary-increment, var(--vvd-color-neutral-800));--_connotation-color-intermediate: var(--vvd-searchable-select-accent-intermediate, var(--vvd-color-neutral-500));--_connotation-color-faint: var(--vvd-searchable-select-accent-faint, var(--vvd-color-neutral-50));--_connotation-color-soft: var(--vvd-searchable-select-accent-soft, var(--vvd-color-neutral-100));--_connotation-color-firm: var(--vvd-searchable-select-accent-firm, var(--vvd-color-canvas-text));--_connotation-color-fierce: var(--vvd-searchable-select-accent-fierce, var(--vvd-color-neutral-700))}.fieldset{--_appearance-color-text: var(--vvd-color-canvas-text);--_appearance-color-fill: var(--vvd-color-canvas);--_appearance-color-outline: var(--vvd-color-neutral-500)}.fieldset.appearance-ghost{--_appearance-color-text: var(--_connotation-color-firm);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.fieldset: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(--vvd-color-neutral-700)}.fieldset: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}.fieldset: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)}.fieldset:where(.disabled,:disabled).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-300);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.fieldset: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)}.fieldset:where(.readonly):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: var(--vvd-color-neutral-600);--_appearance-color-fill: transparent;--_appearance-color-outline: transparent}.fieldset: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)}.fieldset:where(.error):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-alert-50);--_appearance-color-outline: transparent}.fieldset: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)}.fieldset:where(.success):where(:not(.disabled,:disabled)).appearance-ghost{--_appearance-color-text: notSet;--_appearance-color-fill: var(--vvd-color-success-50);--_appearance-color-outline: transparent}.fieldset{display:flex;align-items:center;justify-content:space-between;background-color:var(--_appearance-color-fill);box-shadow:inset 0 0 0 1px var(--_appearance-color-outline);color:var(--_appearance-color-text);font:var(--vvd-typography-base);gap:8px;padding-block:8px;padding-inline:16px;transition:box-shadow .2s,background-color .2s}@supports selector(:has(*)){.fieldset:not(.has-highlighted-option):has(input:focus){box-shadow:0 0 0 4px color-mix(in srgb,var(--vvd-color-cta-500),transparent 85%),inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:1px solid var(--focus-stroke-color, var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset, 0px));--focus-stroke-gap-color: transparent}}@supports not selector(:has(*)){.fieldset:not(.has-highlighted-option):focus-within{box-shadow:0 0 0 4px color-mix(in srgb,var(--vvd-color-cta-500),transparent 85%),inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:1px solid var(--focus-stroke-color, var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset, 0px));--focus-stroke-gap-color: transparent}}:host(:not([shape=pill])) .fieldset{border-radius:8px}:host([shape=pill]) .fieldset{border-radius:24px}.popup-wrapper{position:relative}.content-area{display:flex;overflow:hidden;flex:1;flex-direction:column;gap:8px;min-block-size:24px}.tag-row{display:flex;gap:8px;inline-size:100%}.tag-row.contains-only-input:not(:focus-within){display:contents}.tag-wrapper{overflow:hidden}.tag{max-inline-size:100%}input{box-sizing:border-box;flex:1;border:none;background:none;block-size:24px;font:var(--vvd-typography-base);max-inline-size:100%;min-inline-size:min(100px,40%);outline:none}.contains-only-input input:not(:focus){position:absolute;block-size:0;inline-size:0;min-inline-size:0;opacity:0;pointer-events:none}.listbox{display:flex;flex-direction:column;padding:4px;gap:2px;max-block-size:var(--searchable-select-height, 408px);overflow-y:auto}.empty-message{display:flex;align-items:center;justify-content:center;color:var(--vvd-color-neutral-300);font:var(--vvd-typography-base);min-block-size:40px;text-align:center}::part(popup-base){inline-size:max-content;min-inline-size:var(--_searchable-select-fixed-width, 100%)}slot[name=icon]{font-size:20px}.visually-hidden{position:absolute;overflow:hidden;width:1px;height:1px;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}::slotted([data-vvd-component=option][data-highlighted]){border-radius:8px;box-shadow:0 0 0 4px color-mix(in srgb,var(--vvd-color-cta-500),transparent 85%),inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:1px solid var(--focus-stroke-color, var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset, 0px));--focus-stroke-gap-color: transparent}";
23
23
 
24
- const optionTagStyles = ".base.connotation-cta{--_connotation-color-contrast: var(--vvd-option-tag-cta-contrast, var(--vvd-color-cta-800))}.base:not(.connotation-cta){--_connotation-color-contrast: var(--vvd-option-tag-accent-contrast, var(--vvd-color-neutral-800))}.base{position:relative;display:inline-flex;box-sizing:border-box;align-items:center;background-color:var(--fill-color);block-size:calc(1px*(24 + 4*clamp(-1,var(--vvd-size-density, 0),2)));box-shadow:inset 0 0 0 1px var(--outline-color);color:var(--text-color);column-gap:8px;font:var(--vvd-typography-base-bold);max-inline-size:100%;padding-inline:8px;user-select:none;vertical-align:middle}.base:not(.disabled){--text-color: var(--_connotation-color-contrast);--fill-color: color-mix( in srgb, var(--_connotation-color-contrast), transparent 87.5% );--outline-color: transparent}.base.disabled{--text-color: var(--vvd-color-neutral-300);--fill-color: color-mix( in srgb, var(--vvd-color-neutral-800), transparent 87.5% );--outline-color: transparent}.base:not(.shape-pill){border-radius:4px}.base.shape-pill{border-radius:16px}.label{overflow:hidden;max-inline-size:100%;text-overflow:ellipsis;white-space:nowrap}slot[name=icon]{font-size:calc(calc(1px*(24 + 4*clamp(-1,var(--vvd-size-density, 0),2))) / 1.5);line-height:1}.icon-placeholder{inline-size:calc(calc(1px*(24 + 4*clamp(-1,var(--vvd-size-density, 0),2))) / 1.5)}.remove-button{display:flex;align-items:center;border-radius:inherit;cursor:pointer;outline:none}.disabled .remove-button{pointer-events:none}.remove-button:focus-visible:before{--focus-stroke-gap-color: transparent;box-shadow:0 0 0 4px color-mix(in srgb,var(--vvd-color-cta-500),transparent 85%),inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:1px solid var(--focus-stroke-color, var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset, 0px));position:absolute;z-index:1;display:block;border-radius:inherit;content:\"\";inset:0;pointer-events:none}";
24
+ const optionTagStyles = ".base.connotation-cta{--_connotation-color-contrast: var(--vvd-option-tag-cta-contrast, var(--vvd-color-cta-800))}.base:not(.connotation-cta){--_connotation-color-contrast: var(--vvd-option-tag-accent-contrast, var(--vvd-color-neutral-800))}.base{position:relative;display:inline-flex;box-sizing:border-box;align-items:center;background-color:var(--fill-color);block-size:calc(1px*(24 + 4*clamp(-1,var(--vvd-size-density, 0),2)));box-shadow:inset 0 0 0 1px var(--outline-color);color:var(--text-color);column-gap:8px;font:var(--vvd-typography-base-bold);max-inline-size:100%;padding-inline:8px;user-select:none;vertical-align:middle}.base:not(.disabled){--text-color: var(--_connotation-color-contrast);--fill-color: var(--_connotation-color-soft);--outline-color: transparent}@supports (background-color: color-mix(in srgb,black 50%,white)){.base:not(.disabled){--fill-color: color-mix( in srgb, var(--_connotation-color-contrast), transparent 87.5% )}}.base.disabled{--text-color: var(--vvd-color-neutral-300);--fill-color: var(--vvd-color-neutral-200);--outline-color: transparent}@supports (background-color: color-mix(in srgb,black 50%,white)){.base.disabled{--fill-color: color-mix( in srgb, var(--vvd-color-neutral-800), transparent 87.5% )}}.base:not(.shape-pill){border-radius:4px}.base.shape-pill{border-radius:16px}.label{overflow:hidden;max-inline-size:100%;text-overflow:ellipsis;white-space:nowrap}slot[name=icon]{font-size:calc(calc(1px*(24 + 4*clamp(-1,var(--vvd-size-density, 0),2))) / 1.5);line-height:1}.icon-placeholder{inline-size:calc(calc(1px*(24 + 4*clamp(-1,var(--vvd-size-density, 0),2))) / 1.5)}.remove-button{display:flex;align-items:center;border-radius:inherit;cursor:pointer;outline:none}.disabled .remove-button{pointer-events:none}.remove-button:focus-visible:before{--focus-stroke-gap-color: transparent;box-shadow:0 0 0 4px color-mix(in srgb,var(--vvd-color-cta-500),transparent 85%),inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:1px solid var(--focus-stroke-color, var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset, 0px));position:absolute;z-index:1;display:block;border-radius:inherit;content:\"\";inset:0;pointer-events:none}";
25
25
 
26
26
  var __defProp$1 = Object.defineProperty;
27
27
  var __decorateClass$1 = (decorators, target, key, kind) => {
@@ -449,7 +449,9 @@ class SearchableSelect extends WithFeedback(
449
449
  }
450
450
  #transitionHighlightedOptionTo(index) {
451
451
  if (typeof this._highlightedOptionIndex === "number") {
452
- this._filteredEnabledOptions[this._highlightedOptionIndex]._highlighted = false;
452
+ const prevOption = this._filteredEnabledOptions[this._highlightedOptionIndex];
453
+ prevOption._highlighted = false;
454
+ prevOption.removeAttribute("data-highlighted");
453
455
  }
454
456
  if (typeof index === "number") {
455
457
  if (!this._filteredEnabledOptions.length) {
@@ -465,6 +467,7 @@ class SearchableSelect extends WithFeedback(
465
467
  if (typeof this._highlightedOptionIndex === "number") {
466
468
  const highlightedOption = this._filteredEnabledOptions[this._highlightedOptionIndex];
467
469
  highlightedOption._highlighted = true;
470
+ highlightedOption.setAttribute("data-highlighted", "");
468
471
  scrollIntoView(highlightedOption, this._listbox, "nearest");
469
472
  this._changeDescription = this.locale.searchableSelect.optionFocusedMessage(
470
473
  highlightedOption.text,
@@ -539,7 +542,10 @@ class SearchableSelect extends WithFeedback(
539
542
  return this.disabled || option.disabled;
540
543
  }
541
544
  #textForValue(value) {
542
- return this._slottedOptions?.find((option) => option.value === value)?.text;
545
+ const option = this._slottedOptions?.find(
546
+ (option2) => option2.value === value
547
+ );
548
+ return option?.label;
543
549
  }
544
550
  /**
545
551
  * @internal
@@ -966,7 +972,8 @@ const getStateClasses = (x) => classNames(
966
972
  [`appearance-${x.appearance}`, Boolean(x.appearance)],
967
973
  [`shape-${x.shape}`, Boolean(x.shape)],
968
974
  ["error", Boolean(x.errorValidationMessage)],
969
- ["success", !!x.successText]
975
+ ["success", !!x.successText],
976
+ ["has-highlighted-option", x._highlightedOptionIndex !== null]
970
977
  );
971
978
  function renderLabel() {
972
979
  return html`
@@ -8,7 +8,7 @@ const enums = require('./enums.cjs');
8
8
  const classNames = require('./class-names.cjs');
9
9
  const when = require('./when.cjs');
10
10
 
11
- const styles = ":host{display:flex}.base.connotation-cta{--_connotation-color-firm-all: var(--vvd-selectable-box-cta-firm-all, var(--vvd-color-cta-600));--_connotation-color-pale: var(--vvd-selectable-box-cta-pale, var(--vvd-color-cta-300));--_connotation-color-fierce: var(--vvd-selectable-box-cta-fierce, var(--vvd-color-cta-700));--_connotation-color-faint: var(--vvd-selectable-box-cta-faint, var(--vvd-color-cta-50));--_connotation-color-soft: var(--vvd-selectable-box-cta-soft, var(--vvd-color-cta-100))}.base:not(.connotation-cta){--_connotation-color-firm-all: var(--vvd-selectable-box-accent-firm-all, var(--vvd-color-neutral-600));--_connotation-color-pale: var(--vvd-selectable-box-accent-pale, var(--vvd-color-neutral-300));--_connotation-color-fierce: var(--vvd-selectable-box-accent-fierce, var(--vvd-color-neutral-700));--_connotation-color-faint: var(--vvd-selectable-box-accent-faint, var(--vvd-color-neutral-50));--_connotation-color-soft: var(--vvd-selectable-box-accent-soft, var(--vvd-color-neutral-100))}.base{--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: transparent;--_appearance-color-outline: var(--_connotation-color-pale)}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: transparent;--_appearance-color-outline: var(--_connotation-color-firm-all)}.base:where(.selected):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: var(--_connotation-color-soft);--_appearance-color-outline: var(--_connotation-color-pale)}.base:where(.selected):where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: var(--_connotation-color-faint);--_appearance-color-outline: var(--_connotation-color-firm-all)}.base{position:relative;padding:var(--selectable-box-spacing, 16px);border:1px solid var(--_appearance-color-outline);border-radius:8px;background-color:var(--_appearance-color-fill);inline-size:100%;padding-block-start:calc(var(--selectable-box-spacing, 16px) + 36px);text-align:start}.base:focus-visible{--focus-stroke-gap-color: transparent;box-shadow:0 0 0 4px color-mix(in srgb,var(--vvd-color-cta-500),transparent 85%),inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:1px solid var(--focus-stroke-color, var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset, 0px))}.base.tight{overflow:hidden;min-height:calc(var(--selectable-box-spacing, 16px) * 2 + 22px);padding:0}.base.clickable{cursor:pointer}.control{position:absolute;inset-block-start:var(--selectable-box-spacing, 16px);inset-inline-end:var(--selectable-box-spacing, 16px)}";
11
+ const styles = ":host{display:flex}.base{--control-offset: calc(var(--selectable-box-spacing, 16px) + 36px)}.base.connotation-cta{--_connotation-color-firm-all: var(--vvd-selectable-box-cta-firm-all, var(--vvd-color-cta-600));--_connotation-color-pale: var(--vvd-selectable-box-cta-pale, var(--vvd-color-cta-300));--_connotation-color-fierce: var(--vvd-selectable-box-cta-fierce, var(--vvd-color-cta-700));--_connotation-color-faint: var(--vvd-selectable-box-cta-faint, var(--vvd-color-cta-50));--_connotation-color-soft: var(--vvd-selectable-box-cta-soft, var(--vvd-color-cta-100))}.base:not(.connotation-cta){--_connotation-color-firm-all: var(--vvd-selectable-box-accent-firm-all, var(--vvd-color-neutral-600));--_connotation-color-pale: var(--vvd-selectable-box-accent-pale, var(--vvd-color-neutral-300));--_connotation-color-fierce: var(--vvd-selectable-box-accent-fierce, var(--vvd-color-neutral-700));--_connotation-color-faint: var(--vvd-selectable-box-accent-faint, var(--vvd-color-neutral-50));--_connotation-color-soft: var(--vvd-selectable-box-accent-soft, var(--vvd-color-neutral-100))}.base{--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: transparent;--_appearance-color-outline: var(--_connotation-color-pale)}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: transparent;--_appearance-color-outline: var(--_connotation-color-firm-all)}.base:where(.selected):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: var(--_connotation-color-soft);--_appearance-color-outline: var(--_connotation-color-pale)}.base:where(.selected):where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: var(--_connotation-color-faint);--_appearance-color-outline: var(--_connotation-color-firm-all)}.base{position:relative;padding:var(--selectable-box-spacing, 16px);border:1px solid var(--_appearance-color-outline);border-radius:8px;background-color:var(--_appearance-color-fill);inline-size:100%;text-align:start}.base.control-placement-end-stacked,.base.control-placement-start-stacked{padding-block-start:var(--control-offset)}.base.control-placement-start{padding-inline-start:var(--control-offset)}.base.control-placement-end{padding-inline-end:var(--control-offset)}.base:focus-visible{--focus-stroke-gap-color: transparent;box-shadow:0 0 0 4px color-mix(in srgb,var(--vvd-color-cta-500),transparent 85%),inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:1px solid var(--focus-stroke-color, var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset, 0px))}.base.tight{overflow:hidden;min-height:calc(var(--selectable-box-spacing, 16px) * 2 + 22px);padding:0}.base.clickable{cursor:pointer}.control{position:absolute;inset-block-start:var(--selectable-box-spacing, 16px)}.control.start-stacked,.control.start{inset-inline-start:var(--selectable-box-spacing, 16px)}.control.end-stacked,.control.end{inset-inline-end:var(--selectable-box-spacing, 16px)}";
12
12
 
13
13
  var __defProp = Object.defineProperty;
14
14
  var __decorateClass = (decorators, target, key, kind) => {
@@ -25,6 +25,7 @@ class SelectableBox extends delegatesAria.DelegatesAria(vividElement.VividElemen
25
25
  this.checked = false;
26
26
  this.clickable = false;
27
27
  this.clickableBox = false;
28
+ this.controlPlacement = "end-stacked";
28
29
  this.tight = false;
29
30
  }
30
31
  /**
@@ -63,6 +64,9 @@ __decorateClass([
63
64
  __decorateClass([
64
65
  vividElement.attr({ attribute: "control-type" })
65
66
  ], SelectableBox.prototype, "controlType");
67
+ __decorateClass([
68
+ vividElement.attr({ attribute: "control-placement", mode: "fromView" })
69
+ ], SelectableBox.prototype, "controlPlacement");
66
70
  __decorateClass([
67
71
  vividElement.attr({ mode: "boolean" })
68
72
  ], SelectableBox.prototype, "tight");
@@ -71,14 +75,16 @@ const getClasses = ({
71
75
  connotation,
72
76
  tight,
73
77
  checked,
74
- clickableBox
78
+ clickableBox,
79
+ controlPlacement
75
80
  }) => classNames.classNames(
76
81
  "base",
77
82
  [`connotation-${connotation}`, Boolean(connotation)],
78
83
  ["tight", tight],
79
84
  ["selected", checked],
80
85
  ["clickable", clickableBox],
81
- ["readonly", !clickableBox]
86
+ ["readonly", !clickableBox],
87
+ [`control-placement-${controlPlacement}`, Boolean(controlPlacement)]
82
88
  );
83
89
  function handleControlChange(x) {
84
90
  if (!x.clickableBox) x._handleCheckedChange();
@@ -96,7 +102,7 @@ function checkbox(context) {
96
102
  { onlySpecified: true }
97
103
  )}
98
104
  @change="${(x) => handleControlChange(x)}"
99
- class="control checkbox"
105
+ class="control checkbox ${(x) => x.controlPlacement}"
100
106
  connotation="${(x) => x.connotation === "cta" ? enums.Connotation.CTA : enums.Connotation.Accent}"
101
107
  :checked="${(x) => x.checked}"
102
108
  inert="${(x) => x.clickableBox ? true : null}"
@@ -116,7 +122,7 @@ function radio(context) {
116
122
  { onlySpecified: true }
117
123
  )}
118
124
  @change="${(x) => handleControlChange(x)}"
119
- class="control radio"
125
+ class="control radio ${(x) => x.controlPlacement}"
120
126
  connotation="${(x) => x.connotation === "cta" ? enums.Connotation.CTA : enums.Connotation.Accent}"
121
127
  :checked="${(x) => x.checked}"
122
128
  inert="${(x) => x.clickableBox ? true : null}"
@@ -6,7 +6,7 @@ import { C as Connotation } from './enums.js';
6
6
  import { c as classNames } from './class-names.js';
7
7
  import { w as when } from './when.js';
8
8
 
9
- const styles = ":host{display:flex}.base.connotation-cta{--_connotation-color-firm-all: var(--vvd-selectable-box-cta-firm-all, var(--vvd-color-cta-600));--_connotation-color-pale: var(--vvd-selectable-box-cta-pale, var(--vvd-color-cta-300));--_connotation-color-fierce: var(--vvd-selectable-box-cta-fierce, var(--vvd-color-cta-700));--_connotation-color-faint: var(--vvd-selectable-box-cta-faint, var(--vvd-color-cta-50));--_connotation-color-soft: var(--vvd-selectable-box-cta-soft, var(--vvd-color-cta-100))}.base:not(.connotation-cta){--_connotation-color-firm-all: var(--vvd-selectable-box-accent-firm-all, var(--vvd-color-neutral-600));--_connotation-color-pale: var(--vvd-selectable-box-accent-pale, var(--vvd-color-neutral-300));--_connotation-color-fierce: var(--vvd-selectable-box-accent-fierce, var(--vvd-color-neutral-700));--_connotation-color-faint: var(--vvd-selectable-box-accent-faint, var(--vvd-color-neutral-50));--_connotation-color-soft: var(--vvd-selectable-box-accent-soft, var(--vvd-color-neutral-100))}.base{--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: transparent;--_appearance-color-outline: var(--_connotation-color-pale)}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: transparent;--_appearance-color-outline: var(--_connotation-color-firm-all)}.base:where(.selected):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: var(--_connotation-color-soft);--_appearance-color-outline: var(--_connotation-color-pale)}.base:where(.selected):where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: var(--_connotation-color-faint);--_appearance-color-outline: var(--_connotation-color-firm-all)}.base{position:relative;padding:var(--selectable-box-spacing, 16px);border:1px solid var(--_appearance-color-outline);border-radius:8px;background-color:var(--_appearance-color-fill);inline-size:100%;padding-block-start:calc(var(--selectable-box-spacing, 16px) + 36px);text-align:start}.base:focus-visible{--focus-stroke-gap-color: transparent;box-shadow:0 0 0 4px color-mix(in srgb,var(--vvd-color-cta-500),transparent 85%),inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:1px solid var(--focus-stroke-color, var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset, 0px))}.base.tight{overflow:hidden;min-height:calc(var(--selectable-box-spacing, 16px) * 2 + 22px);padding:0}.base.clickable{cursor:pointer}.control{position:absolute;inset-block-start:var(--selectable-box-spacing, 16px);inset-inline-end:var(--selectable-box-spacing, 16px)}";
9
+ const styles = ":host{display:flex}.base{--control-offset: calc(var(--selectable-box-spacing, 16px) + 36px)}.base.connotation-cta{--_connotation-color-firm-all: var(--vvd-selectable-box-cta-firm-all, var(--vvd-color-cta-600));--_connotation-color-pale: var(--vvd-selectable-box-cta-pale, var(--vvd-color-cta-300));--_connotation-color-fierce: var(--vvd-selectable-box-cta-fierce, var(--vvd-color-cta-700));--_connotation-color-faint: var(--vvd-selectable-box-cta-faint, var(--vvd-color-cta-50));--_connotation-color-soft: var(--vvd-selectable-box-cta-soft, var(--vvd-color-cta-100))}.base:not(.connotation-cta){--_connotation-color-firm-all: var(--vvd-selectable-box-accent-firm-all, var(--vvd-color-neutral-600));--_connotation-color-pale: var(--vvd-selectable-box-accent-pale, var(--vvd-color-neutral-300));--_connotation-color-fierce: var(--vvd-selectable-box-accent-fierce, var(--vvd-color-neutral-700));--_connotation-color-faint: var(--vvd-selectable-box-accent-faint, var(--vvd-color-neutral-50));--_connotation-color-soft: var(--vvd-selectable-box-accent-soft, var(--vvd-color-neutral-100))}.base{--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: transparent;--_appearance-color-outline: var(--_connotation-color-pale)}.base:where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: transparent;--_appearance-color-outline: var(--_connotation-color-firm-all)}.base:where(.selected):where(:not(.disabled,:disabled)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: var(--_connotation-color-soft);--_appearance-color-outline: var(--_connotation-color-pale)}.base:where(.selected):where(.hover,:hover):where(:not(.disabled,:disabled,.readonly)){--_appearance-color-text: var(--_connotation-color-firm-all);--_appearance-color-fill: var(--_connotation-color-faint);--_appearance-color-outline: var(--_connotation-color-firm-all)}.base{position:relative;padding:var(--selectable-box-spacing, 16px);border:1px solid var(--_appearance-color-outline);border-radius:8px;background-color:var(--_appearance-color-fill);inline-size:100%;text-align:start}.base.control-placement-end-stacked,.base.control-placement-start-stacked{padding-block-start:var(--control-offset)}.base.control-placement-start{padding-inline-start:var(--control-offset)}.base.control-placement-end{padding-inline-end:var(--control-offset)}.base:focus-visible{--focus-stroke-gap-color: transparent;box-shadow:0 0 0 4px color-mix(in srgb,var(--vvd-color-cta-500),transparent 85%),inset 0 0 0 3px var(--focus-stroke-gap-color, currentColor);outline:1px solid var(--focus-stroke-color, var(--vvd-color-cta-500));outline-offset:calc(-1px - var(--focus-inset, 0px))}.base.tight{overflow:hidden;min-height:calc(var(--selectable-box-spacing, 16px) * 2 + 22px);padding:0}.base.clickable{cursor:pointer}.control{position:absolute;inset-block-start:var(--selectable-box-spacing, 16px)}.control.start-stacked,.control.start{inset-inline-start:var(--selectable-box-spacing, 16px)}.control.end-stacked,.control.end{inset-inline-end:var(--selectable-box-spacing, 16px)}";
10
10
 
11
11
  var __defProp = Object.defineProperty;
12
12
  var __decorateClass = (decorators, target, key, kind) => {
@@ -23,6 +23,7 @@ class SelectableBox extends DelegatesAria(VividElement) {
23
23
  this.checked = false;
24
24
  this.clickable = false;
25
25
  this.clickableBox = false;
26
+ this.controlPlacement = "end-stacked";
26
27
  this.tight = false;
27
28
  }
28
29
  /**
@@ -61,6 +62,9 @@ __decorateClass([
61
62
  __decorateClass([
62
63
  attr({ attribute: "control-type" })
63
64
  ], SelectableBox.prototype, "controlType");
65
+ __decorateClass([
66
+ attr({ attribute: "control-placement", mode: "fromView" })
67
+ ], SelectableBox.prototype, "controlPlacement");
64
68
  __decorateClass([
65
69
  attr({ mode: "boolean" })
66
70
  ], SelectableBox.prototype, "tight");
@@ -69,14 +73,16 @@ const getClasses = ({
69
73
  connotation,
70
74
  tight,
71
75
  checked,
72
- clickableBox
76
+ clickableBox,
77
+ controlPlacement
73
78
  }) => classNames(
74
79
  "base",
75
80
  [`connotation-${connotation}`, Boolean(connotation)],
76
81
  ["tight", tight],
77
82
  ["selected", checked],
78
83
  ["clickable", clickableBox],
79
- ["readonly", !clickableBox]
84
+ ["readonly", !clickableBox],
85
+ [`control-placement-${controlPlacement}`, Boolean(controlPlacement)]
80
86
  );
81
87
  function handleControlChange(x) {
82
88
  if (!x.clickableBox) x._handleCheckedChange();
@@ -94,7 +100,7 @@ function checkbox(context) {
94
100
  { onlySpecified: true }
95
101
  )}
96
102
  @change="${(x) => handleControlChange(x)}"
97
- class="control checkbox"
103
+ class="control checkbox ${(x) => x.controlPlacement}"
98
104
  connotation="${(x) => x.connotation === "cta" ? Connotation.CTA : Connotation.Accent}"
99
105
  :checked="${(x) => x.checked}"
100
106
  inert="${(x) => x.clickableBox ? true : null}"
@@ -114,7 +120,7 @@ function radio(context) {
114
120
  { onlySpecified: true }
115
121
  )}
116
122
  @change="${(x) => handleControlChange(x)}"
117
- class="control radio"
123
+ class="control radio ${(x) => x.controlPlacement}"
118
124
  connotation="${(x) => x.connotation === "cta" ? Connotation.CTA : Connotation.Accent}"
119
125
  :checked="${(x) => x.checked}"
120
126
  inert="${(x) => x.clickableBox ? true : null}"
@@ -57,6 +57,8 @@ class AudioPlayer extends localized.Localized(vividElement.VividElement) {
57
57
  this.notime = false;
58
58
  this.playbackRates = null;
59
59
  this.#playerEl = new Audio();
60
+ this.#isProgrammaticSliderUpdate = false;
61
+ this.durationFallback = false;
60
62
  this.#pausedChanged = (pausing) => {
61
63
  if (pausing === this.paused) {
62
64
  this.#setPausedState();
@@ -70,18 +72,28 @@ class AudioPlayer extends localized.Localized(vividElement.VividElement) {
70
72
  }
71
73
  this.#setPausedState();
72
74
  };
73
- this.#currentTimeChanged = false;
74
75
  this.#updateProgress = () => {
75
- this.#currentTimeChanged = true;
76
76
  vividElement.Observable.notify(this, "currentTime");
77
- const percent = this.currentTime / this.duration * 100;
78
- this.#sliderEl.value = percent.toString();
79
- if (percent === 100) {
77
+ const duration = this.duration;
78
+ const currentTime = this.currentTime;
79
+ const isValid = Number.isFinite(duration) && duration > 0 && Number.isFinite(currentTime) && currentTime >= 0;
80
+ const percent = isValid ? currentTime / duration * 100 : 0;
81
+ if (this.#sliderEl) {
82
+ this.#isProgrammaticSliderUpdate = true;
83
+ this.#sliderEl.value = percent.toString();
84
+ this.#isProgrammaticSliderUpdate = false;
85
+ }
86
+ if (isValid && percent === 100) {
80
87
  this.pause();
81
88
  }
82
89
  };
83
90
  this.#updateTotalTime = () => {
84
91
  vividElement.Observable.notify(this, "duration");
92
+ if (!Number.isFinite(this.#playerEl.duration) || this.#playerEl.duration <= 0) {
93
+ if (this.durationFallback) {
94
+ this.#fetchAndCacheAudioBuffer();
95
+ }
96
+ }
85
97
  };
86
98
  this.#updateCurrentTimeOnSliderChange = () => {
87
99
  if (!this.paused && this.#sliderEl.isDragging) {
@@ -93,16 +105,28 @@ class AudioPlayer extends localized.Localized(vividElement.VividElement) {
93
105
  }
94
106
  }, 0);
95
107
  }
96
- if (!this.#currentTimeChanged && this.#playerEl) {
108
+ if (this.#isProgrammaticSliderUpdate) {
109
+ return;
110
+ }
111
+ if (this.#playerEl) {
97
112
  this.currentTime = this.duration * Number(this.#sliderEl.value) / 100;
98
113
  }
99
- this.#currentTimeChanged = false;
100
114
  };
101
115
  this.#setPausedState = () => {
102
116
  vividElement.Observable.notify(this, "paused");
103
117
  };
104
- this.#playerEl.addEventListener("timeupdate", this.#updateProgress);
105
- this.#playerEl.addEventListener("loadedmetadata", this.#updateTotalTime);
118
+ }
119
+ srcChanged() {
120
+ if (this.src === void 0) {
121
+ this.#playerEl.removeAttribute("src");
122
+ } else {
123
+ this.#playerEl.src = this.src;
124
+ }
125
+ this.#audioBuffer = void 0;
126
+ if (this.#fetchAbortController) {
127
+ this.#fetchAbortController.abort();
128
+ }
129
+ this.#fetchAbortController = void 0;
106
130
  }
107
131
  get playbackRate() {
108
132
  vividElement.Observable.track(this, "playbackRate");
@@ -112,22 +136,41 @@ class AudioPlayer extends localized.Localized(vividElement.VividElement) {
112
136
  this.#playerEl.playbackRate = value;
113
137
  vividElement.Observable.notify(this, "playbackRate");
114
138
  }
115
- srcChanged() {
116
- if (this.src === void 0) {
117
- this.#playerEl.removeAttribute("src");
118
- } else {
119
- this.#playerEl.src = this.src;
120
- }
121
- }
122
139
  get paused() {
123
140
  vividElement.Observable.track(this, "paused");
124
141
  return this.#playerEl.paused;
125
142
  }
126
143
  set paused(_) {
127
144
  }
145
+ #audioBuffer;
146
+ #fetchAbortController;
147
+ async #fetchAndCacheAudioBuffer() {
148
+ if (this.#audioBuffer || !this.src) return;
149
+ this.#fetchAbortController = new AbortController();
150
+ const signal = this.#fetchAbortController.signal;
151
+ try {
152
+ const response = await fetch(this.src, { signal });
153
+ const arrayBuffer = await response.arrayBuffer();
154
+ const audioContext = new window.AudioContext();
155
+ const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
156
+ audioContext.close();
157
+ this.#audioBuffer = audioBuffer;
158
+ vividElement.Observable.notify(this, "duration");
159
+ } catch (e) {
160
+ } finally {
161
+ this.#fetchAbortController = void 0;
162
+ }
163
+ }
128
164
  get duration() {
129
165
  vividElement.Observable.track(this, "duration");
130
- return this.#playerEl.duration;
166
+ const duration = this.#playerEl.duration;
167
+ if (Number.isFinite(duration) && duration > 0) {
168
+ return duration;
169
+ }
170
+ if (this.#audioBuffer && this.#audioBuffer.duration > 0) {
171
+ return this.#audioBuffer.duration;
172
+ }
173
+ return duration;
131
174
  }
132
175
  set duration(_) {
133
176
  }
@@ -142,15 +185,23 @@ class AudioPlayer extends localized.Localized(vividElement.VividElement) {
142
185
  return this.shadowRoot.querySelector(".slider");
143
186
  }
144
187
  #playerEl;
188
+ #isProgrammaticSliderUpdate;
145
189
  connectedCallback() {
146
190
  super.connectedCallback();
191
+ this.#playerEl.addEventListener("timeupdate", this.#updateProgress);
192
+ this.#playerEl.addEventListener("loadedmetadata", this.#updateTotalTime);
193
+ this.#playerEl.addEventListener("durationchange", this.#updateTotalTime);
147
194
  this.#setSliderInteractionListeners();
148
195
  this.#setPausedState();
196
+ this.#updateProgress();
149
197
  }
150
198
  disconnectedCallback() {
151
199
  super.disconnectedCallback();
152
200
  this.#setSliderInteractionListeners(false);
153
201
  this.pause();
202
+ this.#playerEl.removeEventListener("timeupdate", this.#updateProgress);
203
+ this.#playerEl.removeEventListener("loadedmetadata", this.#updateTotalTime);
204
+ this.#playerEl.removeEventListener("durationchange", this.#updateTotalTime);
154
205
  }
155
206
  play() {
156
207
  this.#pausedChanged(PLAY);
@@ -165,12 +216,24 @@ class AudioPlayer extends localized.Localized(vividElement.VividElement) {
165
216
  }
166
217
  }
167
218
  #pausedChanged;
168
- #currentTimeChanged;
169
219
  #updateProgress;
170
220
  #updateTotalTime;
171
221
  #dragInterval;
172
222
  #updateCurrentTimeOnSliderChange;
173
223
  #setPausedState;
224
+ /**
225
+ * Skips the current time by the skipBy value
226
+ *
227
+ * @param skipDirection - the direction to skip
228
+ *
229
+ * @internal
230
+ */
231
+ skip(skipDirection) {
232
+ const currentTime = this.currentTime;
233
+ const skipValue = parseInt(this.skipBy) * skipDirection;
234
+ const newTime = currentTime + skipValue;
235
+ this.currentTime = Math.max(0, Math.min(this.duration, newTime));
236
+ }
174
237
  }
175
238
  __decorateClass([
176
239
  vividElement.attr({ attribute: "play-button-aria-label" })
@@ -208,16 +271,10 @@ __decorateClass([
208
271
  __decorateClass([
209
272
  vividElement.attr({ attribute: "playback-rates" })
210
273
  ], AudioPlayer.prototype, "playbackRates");
274
+ __decorateClass([
275
+ vividElement.attr({ mode: "boolean", attribute: "duration-fallback" })
276
+ ], AudioPlayer.prototype, "durationFallback");
211
277
 
212
- function skip(audioElement, skipDirection) {
213
- const currentTime = audioElement.currentTime;
214
- const skipValue = parseInt(audioElement.skipBy) * skipDirection;
215
- const newTime = currentTime + skipValue;
216
- audioElement.currentTime = Math.max(
217
- 0,
218
- Math.min(audioElement.duration, newTime)
219
- );
220
- }
221
278
  const getClasses = ({
222
279
  notime,
223
280
  disabled,
@@ -249,7 +306,7 @@ function renderBackwardSkipButtons(context) {
249
306
  const buttonTag = context.tagFor(definition$1.Button);
250
307
  return vividElement.html`
251
308
  <${buttonTag} class="skip backward"
252
- @click="${(element) => skip(element, SKIP_DIRECTIONS.BACKWARD)}"
309
+ @click="${(element) => element.skip(SKIP_DIRECTIONS.BACKWARD)}"
253
310
  icon="${(x) => x.skipBy == enums.MediaSkipBy.Five ? "5-sec-backward-line" : x.skipBy == enums.MediaSkipBy.Thirty ? "30-sec-backward-line" : "10-sec-backward-line"}"
254
311
  size='condensed'
255
312
  aria-label="${(x) => x.skipBackwardButtonAriaLabel || x.locale.audioPlayer.skipBackwardButton}"
@@ -262,7 +319,7 @@ function renderForwardSkipButtons(context) {
262
319
  const buttonTag = context.tagFor(definition$1.Button);
263
320
  return vividElement.html`
264
321
  <${buttonTag} class="skip forward"
265
- @click="${(element) => skip(element, SKIP_DIRECTIONS.FORWARD)}"
322
+ @click="${(element) => element.skip(SKIP_DIRECTIONS.FORWARD)}"
266
323
  icon="${(x) => x.skipBy == enums.MediaSkipBy.Five ? "5-sec-forward-line" : x.skipBy == enums.MediaSkipBy.Thirty ? "30-sec-forward-line" : "10-sec-forward-line"}"
267
324
  size='condensed'
268
325
  aria-label="${(x) => x.skipForwardButtonAriaLabel || x.locale.audioPlayer.skipForwardButton}"
@@ -276,7 +333,6 @@ function renderSlider(context) {
276
333
  return vividElement.html`
277
334
  <${sliderTag}
278
335
  class="slider"
279
- value="0"
280
336
  aria-label="${(x) => x.sliderAriaLabel || x.locale.audioPlayer.sliderLabel}"
281
337
  max="100"
282
338
  aria-valuetext="${(x) => formatTime(x.currentTime)}"
@@ -55,6 +55,8 @@ class AudioPlayer extends Localized(VividElement) {
55
55
  this.notime = false;
56
56
  this.playbackRates = null;
57
57
  this.#playerEl = new Audio();
58
+ this.#isProgrammaticSliderUpdate = false;
59
+ this.durationFallback = false;
58
60
  this.#pausedChanged = (pausing) => {
59
61
  if (pausing === this.paused) {
60
62
  this.#setPausedState();
@@ -68,18 +70,28 @@ class AudioPlayer extends Localized(VividElement) {
68
70
  }
69
71
  this.#setPausedState();
70
72
  };
71
- this.#currentTimeChanged = false;
72
73
  this.#updateProgress = () => {
73
- this.#currentTimeChanged = true;
74
74
  Observable.notify(this, "currentTime");
75
- const percent = this.currentTime / this.duration * 100;
76
- this.#sliderEl.value = percent.toString();
77
- if (percent === 100) {
75
+ const duration = this.duration;
76
+ const currentTime = this.currentTime;
77
+ const isValid = Number.isFinite(duration) && duration > 0 && Number.isFinite(currentTime) && currentTime >= 0;
78
+ const percent = isValid ? currentTime / duration * 100 : 0;
79
+ if (this.#sliderEl) {
80
+ this.#isProgrammaticSliderUpdate = true;
81
+ this.#sliderEl.value = percent.toString();
82
+ this.#isProgrammaticSliderUpdate = false;
83
+ }
84
+ if (isValid && percent === 100) {
78
85
  this.pause();
79
86
  }
80
87
  };
81
88
  this.#updateTotalTime = () => {
82
89
  Observable.notify(this, "duration");
90
+ if (!Number.isFinite(this.#playerEl.duration) || this.#playerEl.duration <= 0) {
91
+ if (this.durationFallback) {
92
+ this.#fetchAndCacheAudioBuffer();
93
+ }
94
+ }
83
95
  };
84
96
  this.#updateCurrentTimeOnSliderChange = () => {
85
97
  if (!this.paused && this.#sliderEl.isDragging) {
@@ -91,16 +103,28 @@ class AudioPlayer extends Localized(VividElement) {
91
103
  }
92
104
  }, 0);
93
105
  }
94
- if (!this.#currentTimeChanged && this.#playerEl) {
106
+ if (this.#isProgrammaticSliderUpdate) {
107
+ return;
108
+ }
109
+ if (this.#playerEl) {
95
110
  this.currentTime = this.duration * Number(this.#sliderEl.value) / 100;
96
111
  }
97
- this.#currentTimeChanged = false;
98
112
  };
99
113
  this.#setPausedState = () => {
100
114
  Observable.notify(this, "paused");
101
115
  };
102
- this.#playerEl.addEventListener("timeupdate", this.#updateProgress);
103
- this.#playerEl.addEventListener("loadedmetadata", this.#updateTotalTime);
116
+ }
117
+ srcChanged() {
118
+ if (this.src === void 0) {
119
+ this.#playerEl.removeAttribute("src");
120
+ } else {
121
+ this.#playerEl.src = this.src;
122
+ }
123
+ this.#audioBuffer = void 0;
124
+ if (this.#fetchAbortController) {
125
+ this.#fetchAbortController.abort();
126
+ }
127
+ this.#fetchAbortController = void 0;
104
128
  }
105
129
  get playbackRate() {
106
130
  Observable.track(this, "playbackRate");
@@ -110,22 +134,41 @@ class AudioPlayer extends Localized(VividElement) {
110
134
  this.#playerEl.playbackRate = value;
111
135
  Observable.notify(this, "playbackRate");
112
136
  }
113
- srcChanged() {
114
- if (this.src === void 0) {
115
- this.#playerEl.removeAttribute("src");
116
- } else {
117
- this.#playerEl.src = this.src;
118
- }
119
- }
120
137
  get paused() {
121
138
  Observable.track(this, "paused");
122
139
  return this.#playerEl.paused;
123
140
  }
124
141
  set paused(_) {
125
142
  }
143
+ #audioBuffer;
144
+ #fetchAbortController;
145
+ async #fetchAndCacheAudioBuffer() {
146
+ if (this.#audioBuffer || !this.src) return;
147
+ this.#fetchAbortController = new AbortController();
148
+ const signal = this.#fetchAbortController.signal;
149
+ try {
150
+ const response = await fetch(this.src, { signal });
151
+ const arrayBuffer = await response.arrayBuffer();
152
+ const audioContext = new window.AudioContext();
153
+ const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
154
+ audioContext.close();
155
+ this.#audioBuffer = audioBuffer;
156
+ Observable.notify(this, "duration");
157
+ } catch (e) {
158
+ } finally {
159
+ this.#fetchAbortController = void 0;
160
+ }
161
+ }
126
162
  get duration() {
127
163
  Observable.track(this, "duration");
128
- return this.#playerEl.duration;
164
+ const duration = this.#playerEl.duration;
165
+ if (Number.isFinite(duration) && duration > 0) {
166
+ return duration;
167
+ }
168
+ if (this.#audioBuffer && this.#audioBuffer.duration > 0) {
169
+ return this.#audioBuffer.duration;
170
+ }
171
+ return duration;
129
172
  }
130
173
  set duration(_) {
131
174
  }
@@ -140,15 +183,23 @@ class AudioPlayer extends Localized(VividElement) {
140
183
  return this.shadowRoot.querySelector(".slider");
141
184
  }
142
185
  #playerEl;
186
+ #isProgrammaticSliderUpdate;
143
187
  connectedCallback() {
144
188
  super.connectedCallback();
189
+ this.#playerEl.addEventListener("timeupdate", this.#updateProgress);
190
+ this.#playerEl.addEventListener("loadedmetadata", this.#updateTotalTime);
191
+ this.#playerEl.addEventListener("durationchange", this.#updateTotalTime);
145
192
  this.#setSliderInteractionListeners();
146
193
  this.#setPausedState();
194
+ this.#updateProgress();
147
195
  }
148
196
  disconnectedCallback() {
149
197
  super.disconnectedCallback();
150
198
  this.#setSliderInteractionListeners(false);
151
199
  this.pause();
200
+ this.#playerEl.removeEventListener("timeupdate", this.#updateProgress);
201
+ this.#playerEl.removeEventListener("loadedmetadata", this.#updateTotalTime);
202
+ this.#playerEl.removeEventListener("durationchange", this.#updateTotalTime);
152
203
  }
153
204
  play() {
154
205
  this.#pausedChanged(PLAY);
@@ -163,12 +214,24 @@ class AudioPlayer extends Localized(VividElement) {
163
214
  }
164
215
  }
165
216
  #pausedChanged;
166
- #currentTimeChanged;
167
217
  #updateProgress;
168
218
  #updateTotalTime;
169
219
  #dragInterval;
170
220
  #updateCurrentTimeOnSliderChange;
171
221
  #setPausedState;
222
+ /**
223
+ * Skips the current time by the skipBy value
224
+ *
225
+ * @param skipDirection - the direction to skip
226
+ *
227
+ * @internal
228
+ */
229
+ skip(skipDirection) {
230
+ const currentTime = this.currentTime;
231
+ const skipValue = parseInt(this.skipBy) * skipDirection;
232
+ const newTime = currentTime + skipValue;
233
+ this.currentTime = Math.max(0, Math.min(this.duration, newTime));
234
+ }
172
235
  }
173
236
  __decorateClass([
174
237
  attr({ attribute: "play-button-aria-label" })
@@ -206,16 +269,10 @@ __decorateClass([
206
269
  __decorateClass([
207
270
  attr({ attribute: "playback-rates" })
208
271
  ], AudioPlayer.prototype, "playbackRates");
272
+ __decorateClass([
273
+ attr({ mode: "boolean", attribute: "duration-fallback" })
274
+ ], AudioPlayer.prototype, "durationFallback");
209
275
 
210
- function skip(audioElement, skipDirection) {
211
- const currentTime = audioElement.currentTime;
212
- const skipValue = parseInt(audioElement.skipBy) * skipDirection;
213
- const newTime = currentTime + skipValue;
214
- audioElement.currentTime = Math.max(
215
- 0,
216
- Math.min(audioElement.duration, newTime)
217
- );
218
- }
219
276
  const getClasses = ({
220
277
  notime,
221
278
  disabled,
@@ -247,7 +304,7 @@ function renderBackwardSkipButtons(context) {
247
304
  const buttonTag = context.tagFor(Button);
248
305
  return html`
249
306
  <${buttonTag} class="skip backward"
250
- @click="${(element) => skip(element, SKIP_DIRECTIONS.BACKWARD)}"
307
+ @click="${(element) => element.skip(SKIP_DIRECTIONS.BACKWARD)}"
251
308
  icon="${(x) => x.skipBy == MediaSkipBy.Five ? "5-sec-backward-line" : x.skipBy == MediaSkipBy.Thirty ? "30-sec-backward-line" : "10-sec-backward-line"}"
252
309
  size='condensed'
253
310
  aria-label="${(x) => x.skipBackwardButtonAriaLabel || x.locale.audioPlayer.skipBackwardButton}"
@@ -260,7 +317,7 @@ function renderForwardSkipButtons(context) {
260
317
  const buttonTag = context.tagFor(Button);
261
318
  return html`
262
319
  <${buttonTag} class="skip forward"
263
- @click="${(element) => skip(element, SKIP_DIRECTIONS.FORWARD)}"
320
+ @click="${(element) => element.skip(SKIP_DIRECTIONS.FORWARD)}"
264
321
  icon="${(x) => x.skipBy == MediaSkipBy.Five ? "5-sec-forward-line" : x.skipBy == MediaSkipBy.Thirty ? "30-sec-forward-line" : "10-sec-forward-line"}"
265
322
  size='condensed'
266
323
  aria-label="${(x) => x.skipForwardButtonAriaLabel || x.locale.audioPlayer.skipForwardButton}"
@@ -274,7 +331,6 @@ function renderSlider(context) {
274
331
  return html`
275
332
  <${sliderTag}
276
333
  class="slider"
277
- value="0"
278
334
  aria-label="${(x) => x.sliderAriaLabel || x.locale.audioPlayer.sliderLabel}"
279
335
  max="100"
280
336
  aria-valuetext="${(x) => formatTime(x.currentTime)}"