@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.
- package/CHANGELOG.md +31 -0
- package/custom-elements.json +2904 -741
- package/dist/checkbox/esp-checkbox-group.d.ts +6 -0
- package/dist/checkbox/esp-checkbox-group.js +10 -5
- package/dist/checkbox/esp-checkbox.d.ts +24 -0
- package/dist/checkbox/esp-checkbox.js +3 -3
- package/dist/cli/theme-check.js +2 -2
- package/dist/date-picker/esp-date-picker.js +6 -6
- package/dist/flyout/esp-flyout.d.ts +1 -1
- package/dist/flyout/esp-flyout.js +3 -9
- package/dist/font-picker/esp-font-picker.js +3 -3
- package/dist/footer/esp-footer.d.ts +1 -1
- package/dist/form-item/esp-form-item.d.ts +35 -0
- package/dist/form-item/esp-form-item.js +16 -11
- package/dist/image/esp-image.d.ts +2 -2
- package/dist/image/esp-image.js +4 -4
- package/dist/image/image-ratio.d.ts +5 -0
- package/dist/image/image-ratio.js +1 -0
- package/dist/image-picker/esp-image-picker.js +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/input/esp-input.d.ts +29 -3
- package/dist/input/esp-input.js +14 -14
- package/dist/menu/esp-menu.d.ts +0 -5
- package/dist/menu/esp-menu.js +4 -4
- package/dist/page/esp-page.d.ts +2 -17
- package/dist/page/esp-page.js +2 -2
- package/dist/page/esp-page.styles.js +8 -32
- package/dist/pickers/esp-pick-one.d.ts +4 -0
- package/dist/pickers/esp-pick-one.js +11 -11
- package/dist/pickers/esp-pick-some.js +8 -8
- package/dist/pickers/esp-picker-base.js +5 -5
- package/dist/pickers/esp-picker-item.js +5 -5
- package/dist/pickers/esp-picker-menu.js +2 -2
- package/dist/pickers/typeahead-controller.js +1 -1
- package/dist/radio-button/esp-radio-button-group.d.ts +6 -0
- package/dist/radio-button/esp-radio-button-group.js +5 -4
- package/dist/radio-button/esp-radio-button.d.ts +22 -0
- package/dist/radio-button/esp-radio-button.js +2 -2
- package/dist/root/esp-root.js +2 -2
- package/dist/shared/enum-converter.js +1 -0
- package/dist/shared/events.d.ts +11 -0
- package/dist/shared/events.js +1 -1
- package/dist/shared/font-helpers.d.ts +0 -2
- package/dist/shared/font-helpers.js +1 -1
- package/dist/shared/form-field-description-controller.js +1 -1
- package/dist/shared/form-item-relay.js +1 -0
- package/dist/shared/justified-layout.d.ts +5 -31
- package/dist/shared/justified-layout.js +1 -1
- package/dist/slider/esp-slider.js +1 -1
- package/dist/switch/esp-switch.js +3 -3
- package/dist/textarea/esp-textarea.js +2 -2
- package/dist/video/esp-video.d.ts +231 -0
- package/dist/video/esp-video.js +253 -0
- package/espalier.css-data.json +40 -16
- package/espalier.token-manifest.json +60 -24
- package/licenses/ASSET_PROVENANCE.md +1 -0
- package/licenses/asset-provenance.json +22 -0
- 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
|
|
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
|
-
*
|
|
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`,
|
|
114
|
-
*
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
`],
|
|
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
|
|
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=[...
|
|
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
|
+
}
|