@taprootio/espalier 4.20.2 → 6.0.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 (59) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/custom-elements.json +2904 -741
  3. package/dist/checkbox/esp-checkbox-group.d.ts +6 -0
  4. package/dist/checkbox/esp-checkbox-group.js +10 -5
  5. package/dist/checkbox/esp-checkbox.d.ts +24 -0
  6. package/dist/checkbox/esp-checkbox.js +3 -3
  7. package/dist/cli/theme-check.js +2 -2
  8. package/dist/date-picker/esp-date-picker.js +6 -6
  9. package/dist/flyout/esp-flyout.d.ts +1 -1
  10. package/dist/flyout/esp-flyout.js +3 -9
  11. package/dist/font-picker/esp-font-picker.js +3 -3
  12. package/dist/footer/esp-footer.d.ts +1 -1
  13. package/dist/form-item/esp-form-item.d.ts +35 -0
  14. package/dist/form-item/esp-form-item.js +16 -11
  15. package/dist/image/esp-image.d.ts +2 -2
  16. package/dist/image/esp-image.js +4 -4
  17. package/dist/image/image-ratio.d.ts +5 -0
  18. package/dist/image/image-ratio.js +1 -0
  19. package/dist/image-picker/esp-image-picker.js +2 -2
  20. package/dist/index.d.ts +2 -1
  21. package/dist/index.js +1 -1
  22. package/dist/input/esp-input.d.ts +29 -3
  23. package/dist/input/esp-input.js +14 -14
  24. package/dist/menu/esp-menu.d.ts +0 -5
  25. package/dist/menu/esp-menu.js +4 -4
  26. package/dist/page/esp-page.d.ts +2 -17
  27. package/dist/page/esp-page.js +2 -2
  28. package/dist/page/esp-page.styles.js +8 -32
  29. package/dist/pickers/esp-pick-one.d.ts +4 -0
  30. package/dist/pickers/esp-pick-one.js +11 -11
  31. package/dist/pickers/esp-pick-some.js +8 -8
  32. package/dist/pickers/esp-picker-base.js +5 -5
  33. package/dist/pickers/esp-picker-item.js +5 -5
  34. package/dist/pickers/esp-picker-menu.js +2 -2
  35. package/dist/pickers/typeahead-controller.js +1 -1
  36. package/dist/radio-button/esp-radio-button-group.d.ts +6 -0
  37. package/dist/radio-button/esp-radio-button-group.js +5 -4
  38. package/dist/radio-button/esp-radio-button.d.ts +22 -0
  39. package/dist/radio-button/esp-radio-button.js +2 -2
  40. package/dist/root/esp-root.js +2 -2
  41. package/dist/shared/enum-converter.js +1 -0
  42. package/dist/shared/events.d.ts +11 -0
  43. package/dist/shared/events.js +1 -1
  44. package/dist/shared/font-helpers.d.ts +0 -2
  45. package/dist/shared/font-helpers.js +1 -1
  46. package/dist/shared/form-field-description-controller.js +1 -1
  47. package/dist/shared/form-item-relay.js +1 -0
  48. package/dist/shared/justified-layout.d.ts +5 -31
  49. package/dist/shared/justified-layout.js +1 -1
  50. package/dist/slider/esp-slider.js +1 -1
  51. package/dist/switch/esp-switch.js +3 -3
  52. package/dist/textarea/esp-textarea.js +2 -2
  53. package/dist/video/esp-video.d.ts +231 -0
  54. package/dist/video/esp-video.js +253 -0
  55. package/espalier.css-data.json +40 -16
  56. package/espalier.token-manifest.json +60 -24
  57. package/licenses/ASSET_PROVENANCE.md +1 -0
  58. package/licenses/asset-provenance.json +22 -0
  59. package/package.json +5 -1
@@ -12,11 +12,6 @@ export interface LayoutImage {
12
12
  width: number;
13
13
  height: number;
14
14
  }
15
- /** A single laid-out row: the items it contains and the row height in px. */
16
- export interface PhotoRow<T extends LayoutImage = LayoutImage> {
17
- images: T[];
18
- height: number;
19
- }
20
15
  /** One image's explicit cell geometry in an album row. */
21
16
  export interface AlbumLayoutItem<T extends LayoutImage = LayoutImage> {
22
17
  /** The source image, retained by reference. */
@@ -72,37 +67,17 @@ export declare function normalizeAlbumMaxRowHeightVh(value: unknown): number;
72
67
  */
73
68
  export declare function normalizeMaxImagesPerRow(value: unknown, fallback?: number, maximum?: number): number;
74
69
  /**
75
- * Compute justified layout rows for a list of images.
70
+ * Compute justified album rows with explicit cell widths.
76
71
  *
77
72
  * Algorithm:
78
- * 1. Add images to a row one at a time, scaled to the target row height
73
+ * 1. Add images to a row one at a time, scaled to the target row height.
79
74
  * 2. When the combined width overflows the container, the row breaks either
80
75
  * before or after the overflowing image — whichever leaves the row height
81
76
  * closer to the target. Keeping the image shrinks the row slightly below
82
77
  * target; pushing it to the next row stretches the row above target.
83
78
  * 3. Scale the finished row so it fills the container width exactly.
84
79
  *
85
- * Every row — including the last — is scaled to fill `containerWidth`
86
- * exactly, except rows clamped by `maxRowHeight`: those keep their aspect
87
- * ratios at the clamped height and no longer span the full width. Items are
88
- * returned by reference in their original order.
89
- *
90
- * @param images Items with intrinsic `width`/`height` (extra fields preserved)
91
- * @param containerWidth Available width in px that each row must fill
92
- * @param targetRowHeight Preferred row height in px before scaling
93
- * @param gap Horizontal gap in px between images within a row
94
- * @param maxRowHeight Ceiling for row heights — keeps a stretched final row
95
- * (or a single image) from ballooning past e.g. half the viewport height
96
- * @param maxImagesPerRow Optional positive-integer ceiling for the number of
97
- * images in each row. Omit it, or pass an invalid value, for an unlimited row
98
- * length.
99
- */
100
- export declare function calculatePhotoLayout<T extends LayoutImage>(images: T[], containerWidth: number, targetRowHeight?: number, gap?: number, maxRowHeight?: number, maxImagesPerRow?: number): PhotoRow<T>[];
101
- /**
102
- * Compute bounded album geometry with explicit cell widths.
103
- *
104
- * This is the opt-in counterpart to {@link calculatePhotoLayout}. Completed
105
- * rows always span the available width. When their justified height exceeds
80
+ * Completed rows always span the available width. When their justified height exceeds
106
81
  * `maxRowHeight`, their cells retain their relative widths while expanding to
107
82
  * the row width at the ceiling; a renderer can use `object-fit: cover` to crop
108
83
  * the resulting cells. A final row below a finite `maxImagesPerRow` instead
@@ -110,8 +85,7 @@ export declare function calculatePhotoLayout<T extends LayoutImage>(images: T[],
110
85
  * the tallest preceding row (or the target height when it is the only row) and
111
86
  * by `maxRowHeight`.
112
87
  *
113
- * With an omitted or invalid `maxImagesPerRow`, every row remains completed.
114
- * That preserves the legacy unlimited-row distribution for callers that have
115
- * not opted into bounded albums.
88
+ * With an omitted or invalid `maxImagesPerRow`, rows are unlimited in length
89
+ * and every row is completed.
116
90
  */
117
91
  export declare function calculateAlbumLayout<T extends LayoutImage>(images: T[], options: AlbumLayoutOptions): AlbumLayoutRow<T>[];
@@ -1 +1 @@
1
- const E=90;function H(t){return typeof t=="number"&&Number.isInteger(t)&&t>=1&&t<=100?t:90}function R(t,r=Number.POSITIVE_INFINITY,u=Number.POSITIVE_INFINITY){return typeof t=="number"&&Number.isInteger(t)&&t>0&&t<=u?t:r}function M(t,r,u=220,a=8,w=Number.POSITIVE_INFINITY,d=Number.POSITIVE_INFINITY){if(t.length===0)return[];const f=R(d),N=o=>o.reduce((c,l)=>c+l.width/l.height,0),I=o=>{const c=(o.length-1)*a;return(r-c)/N(o)},p=o=>o>u?o/u:u/o,m=[];let n=[];const g=(o,c)=>{m.push({images:[...o],height:Math.min(c,w)})};for(let o=0;o<t.length;o++){n.push(t[o]);const l=N(n)*u+(n.length-1)*a>r,b=o===t.length-1;if(l&&n.length>1){const i=I(n),e=I(n.slice(0,-1));p(i)<=p(e)?g(n,i):(n.pop(),o--,g(n,e)),n=[]}else n.length>=f?(g(n,I(n)),n=[]):b&&(g(n,I(n)),n=[])}return m}function P(t,r){if(t.length===0)return[];const u=A(r.containerWidth,0),a=W(r.targetRowHeight,220),w=A(r.gap,8),d=W(r.maxRowHeight,Number.POSITIVE_INFINITY),f=R(r.maxImagesPerRow),N=Number.isFinite(f),I=e=>{const s=e.width/e.height;return Number.isFinite(s)&&s>0?s:1},p=e=>e.reduce((s,h)=>s+I(h),0),m=e=>Math.max(u-(e.length-1)*w,0),n=e=>m(e)/p(e),g=e=>e>a?e/a:a/e,o=[];let c=0;const l=e=>{const s=n(e),h=Math.min(s,d),T=m(e),F=h<s?T/p(e):h;o.push({items:e.map(x=>({image:x,width:I(x)*F})),height:h,isPartial:!1,fillsContainer:!0}),c=Math.max(c,h)},b=e=>{const s=Math.min(n(e),d,c||a);o.push({items:e.map(h=>({image:h,width:I(h)*s})),height:s,isPartial:!0,fillsContainer:!1})};let i=[];for(let e=0;e<t.length;e++){i.push(t[e]);const h=p(i)*a+(i.length-1)*w>u,T=e===t.length-1;if(h&&i.length>1){const _=n(i),F=n(i.slice(0,-1));g(_)<=g(F)||(i.pop(),e--),l(i),i=[]}else i.length>=f?(l(i),i=[]):T&&(N&&i.length<f?b(i):l(i),i=[])}return o}function A(t,r){return typeof t=="number"&&Number.isFinite(t)&&t>=0?t:r}function W(t,r){return typeof t=="number"&&t>0&&(Number.isFinite(t)||t===1/0)?t:r}export{E as DEFAULT_ALBUM_MAX_ROW_HEIGHT_VH,P as calculateAlbumLayout,M as calculatePhotoLayout,H as normalizeAlbumMaxRowHeightVh,R as normalizeMaxImagesPerRow};
1
+ const M=90;function W(t){return typeof t=="number"&&Number.isInteger(t)&&t>=1&&t<=100?t:90}function A(t,o=Number.POSITIVE_INFINITY,c=Number.POSITIVE_INFINITY){return typeof t=="number"&&Number.isInteger(t)&&t>0&&t<=c?t:o}function E(t,o){if(t.length===0)return[];const c=_(o.containerWidth,0),s=x(o.targetRowHeight,220),w=_(o.gap,8),d=x(o.maxRowHeight,Number.POSITIVE_INFINITY),u=A(o.maxImagesPerRow),F=Number.isFinite(u),g=e=>{const i=e.width/e.height;return Number.isFinite(i)&&i>0?i:1},m=e=>e.reduce((i,r)=>i+g(r),0),b=e=>Math.max(c-(e.length-1)*w,0),h=e=>b(e)/m(e),N=e=>e>s?e/s:s/e,p=[];let I=0;const a=e=>{const i=h(e),r=Math.min(i,d),l=b(e),f=r<i?l/m(e):r;p.push({items:e.map(H=>({image:H,width:g(H)*f})),height:r,isPartial:!1,fillsContainer:!0}),I=Math.max(I,r)},T=e=>{const i=Math.min(h(e),d,I||s);p.push({items:e.map(r=>({image:r,width:g(r)*i})),height:i,isPartial:!0,fillsContainer:!1})};let n=[];for(let e=0;e<t.length;e++){n.push(t[e]);const r=m(n)*s+(n.length-1)*w>c,l=e===t.length-1;if(r&&n.length>1){const R=h(n),f=h(n.slice(0,-1));N(R)<=N(f)||(n.pop(),e--),a(n),n=[]}else n.length>=u?(a(n),n=[]):l&&(F&&n.length<u?T(n):a(n),n=[])}return p}function _(t,o){return typeof t=="number"&&Number.isFinite(t)&&t>=0?t:o}function x(t,o){return typeof t=="number"&&t>0&&(Number.isFinite(t)||t===1/0)?t:o}export{M as DEFAULT_ALBUM_MAX_ROW_HEIGHT_VH,E as calculateAlbumLayout,W as normalizeAlbumMaxRowHeightVh,A as normalizeMaxImagesPerRow};
@@ -1,4 +1,4 @@
1
- var o=function(d,t,e,i){var a=arguments.length,r=a<3?t:i===null?i=Object.getOwnPropertyDescriptor(t,e):i,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(d,t,e,i);else for(var h=d.length-1;h>=0;h--)(l=d[h])&&(r=(a<3?l(r):a>3?l(t,e,r):l(t,e))||r);return a>3&&r&&Object.defineProperty(t,e,r),r},p;import{css as v,html as c}from"lit";import{customElement as y,property as n,state as f}from"lit/decorators.js";import{createRef as m,ref as u}from"lit/directives/ref.js";import{classMap as w}from"lit/directives/class-map.js";import{styleMap as _}from"lit/directives/style-map.js";import{ifDefined as b}from"lit/directives/if-defined.js";import{EspalierElementBase as g}from"../shared/esp-element-base.js";import{FormFieldController as S}from"../shared/form-field-controller.js";import{FormFieldDescriptionController as k}from"../shared/form-field-description-controller.js";import{disabledControl as x,focusRing as C}from"../shared/style-fragments.js";import{slotHasContent as $}from"../shared/slot-content.js";let s=p=class extends g{constructor(){super(...arguments),this.internals=this.attachInternals(),this.formCtrl=new S({host:this,internals:this.internals,getFormValue:()=>this.value||null,getValidity:()=>null,onReset:()=>{this.value=String(this._low)},onRestore:t=>{this.value=t},onDisabled:t=>{this.disabled=t}}),this.formItemDescription=new k({host:this,getTarget:()=>this._thumbRef.value}),this.min=0,this.max=100,this.step=1,this.value="0",this.name="",this.disabled=!1,this.label="",this._dragging=!1,this._hasSlotContent=!1,this._trackRef=m(),this._thumbRef=m(),this._slotRef=m(),this._labelId=`esp-slider-label-${p._nextId++}`}get _safeStep(){return Number.isFinite(this.step)&&this.step>0?this.step:1}get _safeMin(){return Number.isFinite(this.min)?this.min:0}get _safeMax(){return Number.isFinite(this.max)?this.max:100}get _stepPrecision(){const t=String(this._safeStep),e=/^(\d+\.?(\d*))e-(\d+)$/.exec(t);if(e){const a=e[2].length,r=Number(e[3]);return a+r}const i=t.indexOf(".");return i===-1?0:t.length-i-1}get _low(){return Math.min(this._safeMin,this._safeMax)}get _high(){return Math.max(this._safeMin,this._safeMax)}_snapToStep(t){const e=this._safeStep,i=this._low,a=this._high,r=Math.round((t-i)/e)*e+i,l=Math.max(i,Math.min(a,r)),h=10**this._stepPrecision;return Math.round(l*h)/h}get numericValue(){const t=Number(this.value);return Number.isNaN(t)?this._snapToStep(this._low):this._snapToStep(t)}get percentage(){const t=this._high-this._low;return t<=0?0:(this.numericValue-this._low)/t*100}_normalizeValue(){const t=String(this.numericValue);t!==this.value&&(this.value=t),this.formCtrl.syncValueSilently()}willUpdate(t){super.willUpdate(t),(t.has("value")||t.has("min")||t.has("max")||t.has("step"))&&this._normalizeValue()}firstUpdated(t){super.firstUpdated(t),this._syncSlotContent()}focus(t){this.focusResolvedElementAfterUpdate(()=>this._thumbRef.value,t)}setFormItemDescription(t){this.formItemDescription.setDescription(t)}validate(){this.formCtrl.validate()}checkValidity(){return this.formCtrl.checkValidity()}_setValueAndNotify(t){const e=String(this._snapToStep(t));e!==this.value&&(this.value=e,this.formCtrl.syncValue(),this.emitValueChanged(e))}_handleKeyDown(t){if(this.disabled)return;const e=this._safeStep;let i=0;switch(t.key){case"ArrowRight":case"ArrowUp":i=e;break;case"ArrowLeft":case"ArrowDown":i=-e;break;case"Home":this._setValueAndNotify(this._low),t.preventDefault();return;case"End":this._setValueAndNotify(this._high),t.preventDefault();return;case"PageUp":i=e*10;break;case"PageDown":i=-e*10;break;default:return}t.preventDefault(),this._setValueAndNotify(this.numericValue+i)}_handlePointerDown(t){if(this.disabled)return;const e=this._thumbRef.value,i=this._trackRef.value;if(!e||!i)return;const a=t.composedPath().includes(e);t.pointerType==="touch"&&!a||(t.preventDefault(),this._dragging=!0,e.setPointerCapture(t.pointerId),e.focus({preventScroll:!0}),this._updateValueFromPointer(t))}_handlePointerMove(t){this._dragging&&this._updateValueFromPointer(t)}_handlePointerUp(){this._endDrag()}_handleLostPointerCapture(){this._endDrag()}_endDrag(){this._dragging&&(this._dragging=!1)}_updateValueFromPointer(t){const e=this._trackRef.value;if(!e)return;const i=e.getBoundingClientRect();if(i.width<=0)return;const a=Math.max(0,Math.min(1,(t.clientX-i.left)/i.width)),r=this._low+a*(this._high-this._low);this._setValueAndNotify(r)}_handleSlotChange(){this._syncSlotContent()}_syncSlotContent(){const t=this._slotRef.value;t&&(this._hasSlotContent=$(t))}formResetCallback(){this.formCtrl.handleFormReset()}formStateRestoreCallback(t){this.formCtrl.handleFormStateRestore(t)}formDisabledCallback(t){this.formCtrl.handleFormDisabled(t)}render(){const t=this.percentage,e=this._hasSlotContent?this._labelId:void 0,i=this._hasSlotContent?void 0:this.label||void 0;return c`
1
+ var o=function(d,t,e,i){var a=arguments.length,r=a<3?t:i===null?i=Object.getOwnPropertyDescriptor(t,e):i,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(d,t,e,i);else for(var h=d.length-1;h>=0;h--)(l=d[h])&&(r=(a<3?l(r):a>3?l(t,e,r):l(t,e))||r);return a>3&&r&&Object.defineProperty(t,e,r),r},p;import{css as v,html as c}from"lit";import{customElement as y,property as n,state as f}from"lit/decorators.js";import{createRef as m,ref as u}from"lit/directives/ref.js";import{classMap as w}from"lit/directives/class-map.js";import{styleMap as _}from"lit/directives/style-map.js";import{ifDefined as b}from"lit/directives/if-defined.js";import{EspalierElementBase as g}from"../shared/esp-element-base.js";import{FormFieldController as S}from"../shared/form-field-controller.js";import{FormFieldDescriptionController as k}from"../shared/form-field-description-controller.js";import{disabledControl as x,focusRing as C}from"../shared/style-fragments.js";import{slotHasContent as $}from"../shared/slot-content.js";let s=p=class extends g{constructor(){super(...arguments),this.internals=this.attachInternals(),this.formCtrl=new S({host:this,internals:this.internals,getFormValue:()=>this.value||null,getValidity:()=>null,onReset:()=>{this.value=String(this._low)},onRestore:t=>{this.value=t},onDisabled:t=>{this.disabled=t}}),this.formItemDescription=new k({host:this,getTarget:()=>this._thumbRef.value}),this.min=0,this.max=100,this.step=1,this.value="0",this.name="",this.disabled=!1,this.label="",this._dragging=!1,this._hasSlotContent=!1,this._trackRef=m(),this._thumbRef=m(),this._slotRef=m(),this._labelId=`esp-slider-label-${p._nextId++}`}get _safeStep(){return Number.isFinite(this.step)&&this.step>0?this.step:1}get _safeMin(){return Number.isFinite(this.min)?this.min:0}get _safeMax(){return Number.isFinite(this.max)?this.max:100}get _stepPrecision(){const t=String(this._safeStep),e=/^(\d+\.?(\d*))e-(\d+)$/.exec(t);if(e){const a=e[2].length,r=Number(e[3]);return a+r}const i=t.indexOf(".");return i===-1?0:t.length-i-1}get _low(){return Math.min(this._safeMin,this._safeMax)}get _high(){return Math.max(this._safeMin,this._safeMax)}_snapToStep(t){const e=this._safeStep,i=this._low,a=this._high,r=Math.round((t-i)/e)*e+i,l=Math.max(i,Math.min(a,r)),h=10**this._stepPrecision;return Math.round(l*h)/h}get numericValue(){const t=Number(this.value);return Number.isNaN(t)?this._snapToStep(this._low):this._snapToStep(t)}get percentage(){const t=this._high-this._low;return t<=0?0:(this.numericValue-this._low)/t*100}_normalizeValue(){const t=String(this.numericValue);t!==this.value&&(this.value=t),this.formCtrl.syncValueSilently()}willUpdate(t){super.willUpdate(t),(t.has("value")||t.has("min")||t.has("max")||t.has("step"))&&this._normalizeValue()}firstUpdated(t){super.firstUpdated(t),this._syncSlotContent()}focus(t){this.focusResolvedElementAfterUpdate(()=>this._thumbRef.value,t)}setFormItemDescription(t){this.formItemDescription.setDescription(t)}setFormItemInvalid(t){this.formItemDescription.setInvalid(t)}validate(){this.formCtrl.validate()}checkValidity(){return this.formCtrl.checkValidity()}_setValueAndNotify(t){const e=String(this._snapToStep(t));e!==this.value&&(this.value=e,this.formCtrl.syncValue(),this.emitValueChanged(e))}_handleKeyDown(t){if(this.disabled)return;const e=this._safeStep;let i=0;switch(t.key){case"ArrowRight":case"ArrowUp":i=e;break;case"ArrowLeft":case"ArrowDown":i=-e;break;case"Home":this._setValueAndNotify(this._low),t.preventDefault();return;case"End":this._setValueAndNotify(this._high),t.preventDefault();return;case"PageUp":i=e*10;break;case"PageDown":i=-e*10;break;default:return}t.preventDefault(),this._setValueAndNotify(this.numericValue+i)}_handlePointerDown(t){if(this.disabled)return;const e=this._thumbRef.value,i=this._trackRef.value;if(!e||!i)return;const a=t.composedPath().includes(e);t.pointerType==="touch"&&!a||(t.preventDefault(),this._dragging=!0,e.setPointerCapture(t.pointerId),e.focus({preventScroll:!0}),this._updateValueFromPointer(t))}_handlePointerMove(t){this._dragging&&this._updateValueFromPointer(t)}_handlePointerUp(){this._endDrag()}_handleLostPointerCapture(){this._endDrag()}_endDrag(){this._dragging&&(this._dragging=!1)}_updateValueFromPointer(t){const e=this._trackRef.value;if(!e)return;const i=e.getBoundingClientRect();if(i.width<=0)return;const a=Math.max(0,Math.min(1,(t.clientX-i.left)/i.width)),r=this._low+a*(this._high-this._low);this._setValueAndNotify(r)}_handleSlotChange(){this._syncSlotContent()}_syncSlotContent(){const t=this._slotRef.value;t&&(this._hasSlotContent=$(t))}formResetCallback(){this.formCtrl.handleFormReset()}formStateRestoreCallback(t){this.formCtrl.handleFormStateRestore(t)}formDisabledCallback(t){this.formCtrl.handleFormDisabled(t)}render(){const t=this.percentage,e=this._hasSlotContent?this._labelId:void 0,i=this._hasSlotContent?void 0:this.label||void 0;return c`
2
2
  <div
3
3
  class=${w({"slider-container":!0,dragging:this._dragging})}
4
4
  @pointerdown=${this._handlePointerDown}
@@ -1,4 +1,4 @@
1
- var s=function(a,e,i,l){var c=arguments.length,o=c<3?e:l===null?l=Object.getOwnPropertyDescriptor(e,i):l,n;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(a,e,i,l);else for(var h=a.length-1;h>=0;h--)(n=a[h])&&(o=(c<3?n(o):c>3?n(e,i,o):n(e,i))||o);return c>3&&o&&Object.defineProperty(e,i,o),o};import{css as m,html as d}from"lit";import{customElement as v,property as r}from"lit/decorators.js";import{classMap as p}from"lit/directives/class-map.js";import{EspalierElementBase as u}from"../shared/esp-element-base.js";import{FormFieldController as b}from"../shared/form-field-controller.js";import{FormFieldDescriptionController as g}from"../shared/form-field-description-controller.js";import{disabledControl as w,focusRing as f,srOnly as y}from"../shared/style-fragments.js";let t=class extends u{constructor(){super(...arguments),this.internals=this.attachInternals(),this.formCtrl=new b({host:this,internals:this.internals,getFormValue:()=>this.checked?this.value||"on":null,getValidity:()=>this.required&&!this.checked?{flags:{valueMissing:!0},message:this.requiredMessage||"Please toggle this switch to continue."}:null,onReset:()=>{this.checked=!1},onRestore:e=>{this.checked=e==="on"||e===this.value},onDisabled:e=>{this.disabled=e}}),this.formItemDescription=new g({host:this,getTarget:()=>this.shadowRoot?.querySelector(".switch-control")}),this.mode="switch",this.offLabel="",this.onLabel="",this.checked=!1,this.value="",this.name="",this.required=!1,this.requiredMessage="",this.disabled=!1}focus(e){this.focusShadowElementAfterUpdate(".switch-control",e)}setFormItemDescription(e){this.formItemDescription.setDescription(e)}validate(){this.formCtrl.validate()}checkValidity(){return this.formCtrl.checkValidity()}toggle(){this.disabled||(this.checked=!this.checked,this.formCtrl.syncValue(),this.emitValueChanged({checked:this.checked,value:this.value}))}handleKeyDown(e){(e.key===" "||e.key==="Enter")&&(e.preventDefault(),this.toggle())}handleLabelSlotChange(){this.requestUpdate()}getCurrentTextModeLabel(){return(this.checked?this.onLabel:this.offLabel).trim()}getTextModeAriaLabel(){const e=this.textContent?.replace(/\s+/g," ").trim()??"",i=this.getCurrentTextModeLabel();return e&&i?`${e}: ${i}`:e||i}formResetCallback(){this.formCtrl.handleFormReset()}formStateRestoreCallback(e){this.formCtrl.handleFormStateRestore(e)}formDisabledCallback(e){this.formCtrl.handleFormDisabled(e)}render(){return this.mode==="text"?d`
1
+ var r=function(a,e,s,l){var c=arguments.length,o=c<3?e:l===null?l=Object.getOwnPropertyDescriptor(e,s):l,n;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(a,e,s,l);else for(var h=a.length-1;h>=0;h--)(n=a[h])&&(o=(c<3?n(o):c>3?n(e,s,o):n(e,s))||o);return c>3&&o&&Object.defineProperty(e,s,o),o};import{css as f,html as d}from"lit";import{customElement as v,property as i}from"lit/decorators.js";import{classMap as p}from"lit/directives/class-map.js";import{EspalierElementBase as u}from"../shared/esp-element-base.js";import{FormFieldController as b}from"../shared/form-field-controller.js";import{FormFieldDescriptionController as g}from"../shared/form-field-description-controller.js";import{disabledControl as w,focusRing as m,srOnly as y}from"../shared/style-fragments.js";let t=class extends u{constructor(){super(...arguments),this.internals=this.attachInternals(),this.formCtrl=new b({host:this,internals:this.internals,getFormValue:()=>this.checked?this.value||"on":null,getValidity:()=>this.required&&!this.checked?{flags:{valueMissing:!0},message:this.requiredMessage||"Please toggle this switch to continue."}:null,onReset:()=>{this.checked=!1},onRestore:e=>{this.checked=e==="on"||e===this.value},onDisabled:e=>{this.disabled=e}}),this.formItemDescription=new g({host:this,getTarget:()=>this.shadowRoot?.querySelector(".switch-control")}),this.mode="switch",this.offLabel="",this.onLabel="",this.checked=!1,this.value="",this.name="",this.required=!1,this.requiredMessage="",this.disabled=!1}focus(e){this.focusShadowElementAfterUpdate(".switch-control",e)}setFormItemDescription(e){this.formItemDescription.setDescription(e)}setFormItemInvalid(e){this.formItemDescription.setInvalid(e)}validate(){this.formCtrl.validate()}checkValidity(){return this.formCtrl.checkValidity()}toggle(){this.disabled||(this.checked=!this.checked,this.formCtrl.syncValue(),this.emitValueChanged({checked:this.checked,value:this.value}))}handleKeyDown(e){(e.key===" "||e.key==="Enter")&&(e.preventDefault(),this.toggle())}handleLabelSlotChange(){this.requestUpdate()}getCurrentTextModeLabel(){return(this.checked?this.onLabel:this.offLabel).trim()}getTextModeAriaLabel(){const e=this.textContent?.replace(/\s+/g," ").trim()??"",s=this.getCurrentTextModeLabel();return e&&s?`${e}: ${s}`:e||s}formResetCallback(){this.formCtrl.handleFormReset()}formStateRestoreCallback(e){this.formCtrl.handleFormStateRestore(e)}formDisabledCallback(e){this.formCtrl.handleFormDisabled(e)}render(){return this.mode==="text"?d`
2
2
  <div
3
3
  class="switch-control text-control"
4
4
  role="switch"
@@ -34,7 +34,7 @@ var s=function(a,e,i,l){var c=arguments.length,o=c<3?e:l===null?l=Object.getOwnP
34
34
  </div>
35
35
  <span class="label"><slot></slot></span>
36
36
  </div>
37
- `}};t.formAssociated=!0,t.styles=[...u.styles,y,f(".switch-control:focus-visible","--esp-switch-focus-shadow"),f(".text-control:focus-visible","--esp-switch-focus-shadow"),w(".switch-control"),m`
37
+ `}};t.clearsFormItemErrorOnChange=!0,t.formAssociated=!0,t.styles=[...u.styles,y,m(".switch-control:focus-visible","--esp-switch-focus-shadow"),m(".text-control:focus-visible","--esp-switch-focus-shadow"),w(".switch-control"),f`
38
38
  :host {
39
39
  display: block;
40
40
  }
@@ -153,4 +153,4 @@ var s=function(a,e,i,l){var c=arguments.length,o=c<3?e:l===null?l=Object.getOwnP
153
153
  .text-option.active {
154
154
  color: var(--esp-switch-text-active-color, var(--esp-color-action-text));
155
155
  }
156
- `],s([r({type:String,reflect:!0})],t.prototype,"mode",void 0),s([r({attribute:"off-label"})],t.prototype,"offLabel",void 0),s([r({attribute:"on-label"})],t.prototype,"onLabel",void 0),s([r({type:Boolean,reflect:!0})],t.prototype,"checked",void 0),s([r({type:String})],t.prototype,"value",void 0),s([r({type:String,reflect:!0})],t.prototype,"name",void 0),s([r({type:Boolean,reflect:!0})],t.prototype,"required",void 0),s([r({attribute:"required-message"})],t.prototype,"requiredMessage",void 0),s([r({type:Boolean,reflect:!0})],t.prototype,"disabled",void 0),t=s([v("esp-switch")],t);export{t as EspalierSwitch};
156
+ `],r([i({type:String,reflect:!0})],t.prototype,"mode",void 0),r([i({attribute:"off-label"})],t.prototype,"offLabel",void 0),r([i({attribute:"on-label"})],t.prototype,"onLabel",void 0),r([i({type:Boolean,reflect:!0})],t.prototype,"checked",void 0),r([i({type:String})],t.prototype,"value",void 0),r([i({type:String,reflect:!0})],t.prototype,"name",void 0),r([i({type:Boolean,reflect:!0})],t.prototype,"required",void 0),r([i({attribute:"required-message"})],t.prototype,"requiredMessage",void 0),r([i({type:Boolean,reflect:!0})],t.prototype,"disabled",void 0),t=r([v("esp-switch")],t);export{t as EspalierSwitch};
@@ -1,4 +1,4 @@
1
- var r=function(n,e,i,l){var h=arguments.length,a=h<3?e:l===null?l=Object.getOwnPropertyDescriptor(e,i):l,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")a=Reflect.decorate(n,e,i,l);else for(var u=n.length-1;u>=0;u--)(d=n[u])&&(a=(h<3?d(a):h>3?d(e,i,a):d(e,i))||a);return h>3&&a&&Object.defineProperty(e,i,a),a};import{css as m,html as p}from"lit";import{customElement as f,property as s}from"lit/decorators.js";import{ifDefined as o}from"lit/directives/if-defined.js";import{createRef as v,ref as g}from"lit/directives/ref.js";import{EspalierElementBase as c}from"../shared/esp-element-base.js";import{FormFieldController as y}from"../shared/form-field-controller.js";import{FormFieldDescriptionController as b}from"../shared/form-field-description-controller.js";let t=class extends c{constructor(){super(...arguments),this.internals=this.attachInternals(),this.theTextarea=v(),this.formCtrl=new y({host:this,internals:this.internals,getFormValue:()=>this.value||null,getValidity:()=>this._getValidity(),getValidationAnchor:()=>this.theTextarea.value??this,onReset:()=>{this.value="",this._hasVisibleError=!1},onRestore:e=>{this.value=e},onDisabled:e=>{this.disabled=e}}),this.formItemDescription=new b({host:this,getTarget:()=>this.theTextarea.value}),this._hasVisibleError=!1,this.fieldName="",this.value="",this.name="",this.required=!1,this.requiredMessage="",this.validationMessage="",this.disabled=!1,this._trackVisibleError=e=>{const i=e.detail;this._hasVisibleError=!i.valid}}handleInput(e){const i=e.target;this.value=i.value,this._syncInput()}_syncInput(){this._hasVisibleError?this.formCtrl.syncValue():this.formCtrl.syncValueSilently(),this.emitValueChanged(this.value)}_handleBlur(){this.formCtrl.syncValue()}_getValidity(){const e=this.theTextarea.value;if(e&&!e.validity.valid){const i=e.validity,l={valueMissing:i.valueMissing,tooLong:i.tooLong,tooShort:i.tooShort};return{flags:l,message:this._getFriendlyMessage(l)}}return this.required&&!this.value?{flags:{valueMissing:!0},message:this.requiredMessage||"Please fill out this field."}:null}_getFriendlyMessage(e){return e.valueMissing?this.requiredMessage||"Please fill out this field.":e.tooShort?this.validationMessage||`Must be at least ${this.minlength} characters.`:e.tooLong?this.validationMessage||`Must be no more than ${this.maxlength} characters.`:"Please enter a valid value."}focus(e){this.focusResolvedElementAfterUpdate(()=>this.theTextarea.value,e)}setFormItemDescription(e){this.formItemDescription.setDescription(e)}setFormItemLabel(e){this.formItemDescription.setLabel(e)}validate(){this.formCtrl.validate()}checkValidity(){return this.formCtrl.checkValidity()}formResetCallback(){this.formCtrl.handleFormReset()}formStateRestoreCallback(e){this.formCtrl.handleFormStateRestore(e)}formDisabledCallback(e){this.formCtrl.handleFormDisabled(e)}connectedCallback(){super.connectedCallback(),this.addEventListener("esp-validity-changed",this._trackVisibleError)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener("esp-validity-changed",this._trackVisibleError)}render(){return p`
1
+ var r=function(n,e,i,l){var h=arguments.length,a=h<3?e:l===null?l=Object.getOwnPropertyDescriptor(e,i):l,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")a=Reflect.decorate(n,e,i,l);else for(var u=n.length-1;u>=0;u--)(d=n[u])&&(a=(h<3?d(a):h>3?d(e,i,a):d(e,i))||a);return h>3&&a&&Object.defineProperty(e,i,a),a};import{css as c,html as p}from"lit";import{customElement as f,property as s}from"lit/decorators.js";import{ifDefined as o}from"lit/directives/if-defined.js";import{createRef as v,ref as g}from"lit/directives/ref.js";import{EspalierElementBase as m}from"../shared/esp-element-base.js";import{FormFieldController as y}from"../shared/form-field-controller.js";import{FormFieldDescriptionController as b}from"../shared/form-field-description-controller.js";let t=class extends m{constructor(){super(...arguments),this.internals=this.attachInternals(),this.theTextarea=v(),this.formCtrl=new y({host:this,internals:this.internals,getFormValue:()=>this.value||null,getValidity:()=>this._getValidity(),getValidationAnchor:()=>this.theTextarea.value??this,onReset:()=>{this.value="",this._hasVisibleError=!1},onRestore:e=>{this.value=e},onDisabled:e=>{this.disabled=e}}),this.formItemDescription=new b({host:this,getTarget:()=>this.theTextarea.value}),this._hasVisibleError=!1,this.fieldName="",this.value="",this.name="",this.required=!1,this.requiredMessage="",this.validationMessage="",this.disabled=!1,this._trackVisibleError=e=>{const i=e.detail;this._hasVisibleError=!i.valid}}handleInput(e){const i=e.target;this.value=i.value,this._syncInput()}_syncInput(){this._hasVisibleError?this.formCtrl.syncValue():this.formCtrl.syncValueSilently(),this.emitValueChanged(this.value)}_handleBlur(){this.formCtrl.syncValue()}_getValidity(){const e=this.theTextarea.value;if(e&&!e.validity.valid){const i=e.validity,l={valueMissing:i.valueMissing,tooLong:i.tooLong,tooShort:i.tooShort};return{flags:l,message:this._getFriendlyMessage(l)}}return this.required&&!this.value?{flags:{valueMissing:!0},message:this.requiredMessage||"Please fill out this field."}:null}_getFriendlyMessage(e){return e.valueMissing?this.requiredMessage||"Please fill out this field.":e.tooShort?this.validationMessage||`Must be at least ${this.minlength} characters.`:e.tooLong?this.validationMessage||`Must be no more than ${this.maxlength} characters.`:"Please enter a valid value."}focus(e){this.focusResolvedElementAfterUpdate(()=>this.theTextarea.value,e)}setFormItemDescription(e){this.formItemDescription.setDescription(e)}setFormItemInvalid(e){this.formItemDescription.setInvalid(e)}setFormItemLabel(e){this.formItemDescription.setLabel(e)}validate(){this.formCtrl.validate()}checkValidity(){return this.formCtrl.checkValidity()}formResetCallback(){this.formCtrl.handleFormReset()}formStateRestoreCallback(e){this.formCtrl.handleFormStateRestore(e)}formDisabledCallback(e){this.formCtrl.handleFormDisabled(e)}connectedCallback(){super.connectedCallback(),this.addEventListener("esp-validity-changed",this._trackVisibleError)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener("esp-validity-changed",this._trackVisibleError)}render(){return p`
2
2
  <div class="esp-field">
3
3
  <textarea
4
4
  id=${this.fieldName}
@@ -15,7 +15,7 @@ var r=function(n,e,i,l){var h=arguments.length,a=h<3?e:l===null?l=Object.getOwnP
15
15
  ?disabled=${this.disabled}
16
16
  ></textarea>
17
17
  </div>
18
- `}};t.formAssociated=!0,t.styles=[...c.styles,m`
18
+ `}};t.formAssociated=!0,t.styles=[...m.styles,c`
19
19
  .esp-field {
20
20
  margin: 1px;
21
21
 
@@ -0,0 +1,231 @@
1
+ import { type PropertyValues } from "lit";
2
+ import { EspalierElementBase } from "../shared/esp-element-base.js";
3
+ /** The HLS master-playlist media type, and the default `type`. */
4
+ export declare const HLS_MEDIA_TYPE = "application/vnd.apple.mpegurl";
5
+ /** The `aspect-ratio` used when the attribute is absent or invalid. */
6
+ export declare const DEFAULT_VIDEO_ASPECT_RATIO = "16 / 9";
7
+ export type VideoPreload = "none" | "metadata" | "auto";
8
+ export type VideoControls = "native" | "none";
9
+ export type VideoCrossOrigin = "" | "anonymous" | "use-credentials";
10
+ /**
11
+ * How the playing source reached the video: `native` is playing `src`, and
12
+ * `fallback` is playing `fallback-src`.
13
+ */
14
+ export type VideoSourceMode = "native" | "fallback";
15
+ /**
16
+ * Why playback failed: `unsupported` when no `src` is set, or the browser
17
+ * cannot play `type`, and there is no fallback; `media` when the video element
18
+ * reported an error while loading or playing.
19
+ */
20
+ export type VideoErrorReason = "unsupported" | "media";
21
+ /**
22
+ * Detail of `esp-video-ready` on `esp-video`.
23
+ *
24
+ * @docUrl /api/video-ready-detail
25
+ * @menuGroup Event Details
26
+ * @menuLabel VideoReadyDetail
27
+ */
28
+ export interface VideoReadyDetail {
29
+ /** The element's `src`. */
30
+ src: string;
31
+ /** How the source was attached. */
32
+ mode: VideoSourceMode;
33
+ /** The media duration in seconds; `Infinity` for a live stream. */
34
+ duration: number;
35
+ }
36
+ /**
37
+ * Detail of `esp-video-play` on `esp-video`.
38
+ *
39
+ * @docUrl /api/video-play-detail
40
+ * @menuGroup Event Details
41
+ * @menuLabel VideoPlayDetail
42
+ */
43
+ export interface VideoPlayDetail {
44
+ /** The element's `src`. */
45
+ src: string;
46
+ /** How the source was attached. */
47
+ mode: VideoSourceMode;
48
+ /** The playback position, in seconds, at which playback started. */
49
+ currentTime: number;
50
+ /** Whether `autoplay` started this playback rather than the visitor. */
51
+ autoplay: boolean;
52
+ }
53
+ /**
54
+ * Detail of `esp-video-error` on `esp-video`.
55
+ *
56
+ * @docUrl /api/video-error-detail
57
+ * @menuGroup Event Details
58
+ * @menuLabel VideoErrorDetail
59
+ */
60
+ export interface VideoErrorDetail {
61
+ /** The element's `src`. */
62
+ src: string;
63
+ /** The attachment that failed, or `null` when nothing was attached. */
64
+ mode: VideoSourceMode | null;
65
+ /** Why playback failed. */
66
+ reason: VideoErrorReason;
67
+ /** A short developer-facing description; not shown to visitors. */
68
+ message: string;
69
+ /** Whether the element is now trying `fallback-src`. */
70
+ fallback: boolean;
71
+ }
72
+ /**
73
+ * A native video player: a `<video>` element with a lazy poster, a fixed
74
+ * aspect ratio, captions, native controls, and visible loading and error
75
+ * states. It is never an iframe and never loads a third-party player.
76
+ *
77
+ * Nothing but the poster loads until the visitor presses play, so a page of
78
+ * videos costs one image request each. The play affordance over the poster is
79
+ * a real button named from `label` or `poster-alt`.
80
+ *
81
+ * ```html
82
+ * <esp-video
83
+ * src="/assets/esp-video/espalier-sample.mp4"
84
+ * type="video/mp4"
85
+ * poster="/assets/esp-video/espalier-sample-poster.jpg"
86
+ * poster-alt="Espalier's palette drifting across a trellis grid"
87
+ * playsinline
88
+ * ></esp-video>
89
+ * ```
90
+ *
91
+ * ### Sources
92
+ *
93
+ * The element plays `src` only where the browser reports it can play `type`.
94
+ * `type` is an HLS master playlist by default, which Safari, iOS, and current
95
+ * Chrome play natively; elsewhere `fallback-src` (an MP4) plays instead.
96
+ * Espalier attaches no streaming library, so for a source every browser can
97
+ * play, set `type="video/mp4"`.
98
+ *
99
+ * ### Captions
100
+ *
101
+ * Give the element `<track>` children. A media element only reads its own
102
+ * child tracks, so the element mirrors them into its video when it attaches
103
+ * the source; `kind`, `srclang`, `label`, and `default` carry through. With
104
+ * the default `preload="none"`, no caption file loads before the visitor
105
+ * presses play.
106
+ *
107
+ * ```html
108
+ * <esp-video
109
+ * src="/assets/esp-video/espalier-sample.mp4"
110
+ * type="video/mp4"
111
+ * poster="/assets/esp-video/espalier-sample-poster.jpg"
112
+ * poster-alt="The trellis sample, with English captions"
113
+ * aspect-ratio="21 / 9"
114
+ * >
115
+ * <track kind="captions" src="/assets/esp-video/espalier-sample.en.vtt" srclang="en" label="English" default />
116
+ * </esp-video>
117
+ * ```
118
+ *
119
+ * ### Autoplay
120
+ *
121
+ * `autoplay` starts playback once the element is admitted (immediately, or
122
+ * near the viewport with `defer-offscreen`). It always plays muted: while
123
+ * `autoplay` is set the video stays muted whatever `muted` says, so a page
124
+ * never starts sound unprompted. It does not start for a visitor who prefers
125
+ * reduced motion, or where the browser blocks it; the poster and play button
126
+ * remain.
127
+ *
128
+ * @slot - `<track>` elements for captions, subtitles, descriptions, and chapters.
129
+ * @slot error - Replaces the error message shown over the poster.
130
+ * @csspart frame - The element's full box.
131
+ * @csspart video - The native `<video>` element.
132
+ * @csspart poster - The layer over the video holding the poster, play button, and messages.
133
+ * @csspart poster-image - The poster `<img>`.
134
+ * @csspart play - The play `<button>`, which covers the poster.
135
+ * @csspart play-icon - The visible play disc inside the button.
136
+ * @csspart message - The error message.
137
+ * @cssprop --esp-video-surface - Background behind the video and an absent poster. Defaults to a near-black derived from `--esp-color-text`.
138
+ * @cssprop --esp-video-border-radius - Corner radius. Defaults to `var(--esp-size-border-radius)`.
139
+ * @cssprop --esp-video-object-fit - How the video fills its box. Defaults to `contain`; the poster always covers.
140
+ * @cssprop --esp-video-accent - `accent-color` for the native controls, where the browser honors it. Defaults to `var(--esp-color-primary)`.
141
+ * @cssprop --esp-video-focus-outline - Focus-visible outline on the play button, the video, and the error message. Defaults to `3px solid var(--esp-color-link)`.
142
+ * @cssprop --esp-video-play-size - Diameter of the play disc. Defaults to `var(--esp-size-huge)`.
143
+ * @cssprop --esp-video-play-background - Fill of the play disc. Defaults to `var(--esp-color-background)` at 90% opacity.
144
+ * @cssprop --esp-video-play-color - Play glyph and loading-indicator color. Defaults to `var(--esp-color-text)`.
145
+ * @cssprop --esp-video-message-background - Error message background. Defaults to `var(--esp-color-background)`.
146
+ * @cssprop --esp-video-message-color - Error message text color. Defaults to `var(--esp-color-text)`.
147
+ * @event {CustomEvent<VideoReadyDetail>} esp-video-ready - Bubbles across shadow boundaries once the attached source has loaded its metadata; `detail` is `{ src, mode, duration }`. Fires once per attached source.
148
+ * @event {CustomEvent<VideoPlayDetail>} esp-video-play - Bubbles across shadow boundaries each time playback starts, or resumes after a pause, on the media's `playing`. Recovery from buffering or a seek is not reported, and a source that fails first reports no play; `detail` is `{ src, mode, currentTime, autoplay }`.
149
+ * @event {CustomEvent<VideoErrorDetail>} esp-video-error - Bubbles across shadow boundaries when a source fails; `detail` is `{ src, mode, reason, message, fallback }`. When `fallback` is true the element is already trying `fallback-src`.
150
+ * @docPageTitle Video
151
+ * @docUrl /components/video
152
+ * @menuGroup Media
153
+ * @menuLabel Video
154
+ * @menuIcon photo
155
+ */
156
+ export declare class EspalierVideo extends EspalierElementBase {
157
+ /** The media URL: an HLS master playlist by default, or a file matching `type`. */
158
+ src: string;
159
+ /**
160
+ * The media type of `src`, checked with `canPlayType` to choose between
161
+ * `src` and `fallback-src`. `video/mp4` plays as a plain file.
162
+ */
163
+ type: string;
164
+ /** Poster image URL, shown until playback starts and behind error messages. */
165
+ poster: string;
166
+ /** Describes the poster; names the play button when `label` is unset. */
167
+ posterAlt: string;
168
+ /**
169
+ * The play button's accessible name. Defaults to `Play video: <poster-alt>`,
170
+ * or `Play video` with no poster text.
171
+ */
172
+ label: string;
173
+ /**
174
+ * The box's aspect ratio, as a positive number or `number / number`. Invalid
175
+ * values fall back to `16 / 9`.
176
+ */
177
+ aspectRatio: string;
178
+ /**
179
+ * How much media to load before play intent. `none` (the default) loads
180
+ * only the poster. `metadata` and `auto` apply where the browser plays
181
+ * `type`; the choice of the fallback over it still waits for play intent.
182
+ * A preloaded source that fails switches to `fallback-src` at once.
183
+ */
184
+ preload: VideoPreload;
185
+ /** Start muted playback once admitted. Implies `muted`. */
186
+ autoplay: boolean;
187
+ /**
188
+ * Start muted. Always on while `autoplay` is set. Clearing it (or
189
+ * `autoplay`) unmutes only a paused video; a playing one stays muted until
190
+ * the visitor unmutes it.
191
+ */
192
+ muted: boolean;
193
+ /** Restart from the beginning when playback ends. */
194
+ loop: boolean;
195
+ /** Play inline on iOS rather than entering full screen. Needed for inline autoplay there. */
196
+ playsinline: boolean;
197
+ /**
198
+ * `native` (the default) shows the browser's controls once playback starts.
199
+ * `none` shows none; use it only for short decorative loops, since a visitor
200
+ * then has no way to pause.
201
+ */
202
+ controls: VideoControls;
203
+ /**
204
+ * Defer everything — the poster, `preload`, and `autoplay` — until the
205
+ * element is within 200px of the viewport. The poster is not rendered
206
+ * before then, so the browser's own lazy-loading distance cannot fetch it
207
+ * early.
208
+ */
209
+ deferOffscreen: boolean;
210
+ /**
211
+ * An MP4 played when the browser cannot play `type`, and tried once when
212
+ * the primary source fails.
213
+ */
214
+ fallbackSrc: string;
215
+ /**
216
+ * CORS mode for the video's requests, as on `<video crossorigin>`. Needed
217
+ * for caption tracks served from another origin.
218
+ */
219
+ crossOrigin: VideoCrossOrigin;
220
+ connectedCallback(): void;
221
+ disconnectedCallback(): void;
222
+ protected willUpdate(changedProperties: PropertyValues): void;
223
+ protected updated(changedProperties: PropertyValues): void;
224
+ protected render(): import("lit-html").TemplateResult<1>;
225
+ static styles: import("lit").CSSResult[];
226
+ }
227
+ declare global {
228
+ interface HTMLElementTagNameMap {
229
+ "esp-video": EspalierVideo;
230
+ }
231
+ }