@aurodesignsystem-dev/auro-datetime 0.0.0-pr111.0 → 0.0.0-pr112.1
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/README.md +30 -41
- package/custom-elements.json +373 -0
- package/demo/api.md +252 -233
- package/demo/api.min.js +595 -1
- package/demo/index.md +24 -25
- package/demo/index.min.js +595 -1
- package/demo/readme.md +117 -0
- package/dist/auro-datetime-CRsYbYbt.js +6 -0
- package/dist/index.d.ts +75 -71
- package/dist/index.js +1 -1
- package/dist/registered.js +1 -1
- package/package.json +8 -6
- package/demo/auro-datetime.min.js +0 -608
- package/dist/auro-datetime-39FU0ZIU.js +0 -6
package/demo/index.min.js
CHANGED
|
@@ -1,4 +1,598 @@
|
|
|
1
|
-
|
|
1
|
+
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
2
|
+
// See LICENSE in the project root for license information.
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------
|
|
5
|
+
|
|
6
|
+
/* eslint-disable line-comment-position, no-inline-comments, no-confusing-arrow, no-nested-ternary, implicit-arrow-linebreak */
|
|
7
|
+
|
|
8
|
+
class AuroLibraryRuntimeUtils {
|
|
9
|
+
|
|
10
|
+
/* eslint-disable jsdoc/require-param */
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* This will register a new custom element with the browser.
|
|
14
|
+
* @param {String} name - The name of the custom element.
|
|
15
|
+
* @param {Object} componentClass - The class to register as a custom element.
|
|
16
|
+
* @returns {void}
|
|
17
|
+
*/
|
|
18
|
+
registerComponent(name, componentClass) {
|
|
19
|
+
if (!customElements.get(name)) {
|
|
20
|
+
customElements.define(name, class extends componentClass {});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Finds and returns the closest HTML Element based on a selector.
|
|
26
|
+
* @returns {void}
|
|
27
|
+
*/
|
|
28
|
+
closestElement(
|
|
29
|
+
selector, // selector like in .closest()
|
|
30
|
+
base = this, // extra functionality to skip a parent
|
|
31
|
+
__Closest = (el, found = el && el.closest(selector)) =>
|
|
32
|
+
!el || el === document || el === window
|
|
33
|
+
? null // standard .closest() returns null for non-found selectors also
|
|
34
|
+
: found
|
|
35
|
+
? found // found a selector INside this element
|
|
36
|
+
: __Closest(el.getRootNode().host) // recursion!! break out to parent DOM
|
|
37
|
+
) {
|
|
38
|
+
return __Closest(base);
|
|
39
|
+
}
|
|
40
|
+
/* eslint-enable jsdoc/require-param */
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* If the element passed is registered with a different tag name than what is passed in, the tag name is added as an attribute to the element.
|
|
44
|
+
* @param {Object} elem - The element to check.
|
|
45
|
+
* @param {String} tagName - The name of the Auro component to check for or add as an attribute.
|
|
46
|
+
* @returns {void}
|
|
47
|
+
*/
|
|
48
|
+
handleComponentTagRename(elem, tagName) {
|
|
49
|
+
const tag = tagName.toLowerCase();
|
|
50
|
+
const elemTag = elem.tagName.toLowerCase();
|
|
51
|
+
|
|
52
|
+
if (elemTag !== tag) {
|
|
53
|
+
elem.setAttribute(tag, true);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Validates if an element is a specific Auro component.
|
|
59
|
+
* @param {Object} elem - The element to validate.
|
|
60
|
+
* @param {String} tagName - The name of the Auro component to check against.
|
|
61
|
+
* @returns {Boolean} - Returns true if the element is the specified Auro component.
|
|
62
|
+
*/
|
|
63
|
+
elementMatch(elem, tagName) {
|
|
64
|
+
const tag = tagName.toLowerCase();
|
|
65
|
+
const elemTag = elem.tagName.toLowerCase();
|
|
66
|
+
|
|
67
|
+
return elemTag === tag || elem.hasAttribute(tag);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Gets the text content of a named slot.
|
|
72
|
+
* @returns {String}
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
getSlotText(elem, name) {
|
|
76
|
+
const slot = elem.shadowRoot?.querySelector(`slot[name="${name}"]`);
|
|
77
|
+
const nodes = slot?.assignedNodes({ flatten: true }) || [];
|
|
78
|
+
const text = nodes.map(n => n.textContent?.trim()).join(' ').trim();
|
|
79
|
+
|
|
80
|
+
return text || null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @license
|
|
86
|
+
* Copyright 2019 Google LLC
|
|
87
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
88
|
+
*/
|
|
89
|
+
const t$1=globalThis,e$2=t$1.ShadowRoot&&(void 0===t$1.ShadyCSS||t$1.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,s$2=Symbol(),o$3=new WeakMap;let n$2 = class n{constructor(t,e,o){if(this._$cssResult$=true,o!==s$2)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e;}get styleSheet(){let t=this.o;const s=this.t;if(e$2&&void 0===t){const e=void 0!==s&&1===s.length;e&&(t=o$3.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&o$3.set(s,t));}return t}toString(){return this.cssText}};const r$2=t=>new n$2("string"==typeof t?t:t+"",void 0,s$2),S$1=(s,o)=>{if(e$2)s.adoptedStyleSheets=o.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of o){const o=document.createElement("style"),n=t$1.litNonce;void 0!==n&&o.setAttribute("nonce",n),o.textContent=e.cssText,s.appendChild(o);}},c$2=e$2?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const s of t.cssRules)e+=s.cssText;return r$2(e)})(t):t;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @license
|
|
93
|
+
* Copyright 2017 Google LLC
|
|
94
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
95
|
+
*/const{is:i$2,defineProperty:e$1,getOwnPropertyDescriptor:h$1,getOwnPropertyNames:r$1,getOwnPropertySymbols:o$2,getPrototypeOf:n$1}=Object,a$1=globalThis,c$1=a$1.trustedTypes,l$1=c$1?c$1.emptyScript:"",p$1=a$1.reactiveElementPolyfillSupport,d$1=(t,s)=>t,u$1={toAttribute(t,s){switch(s){case Boolean:t=t?l$1:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t);}return t},fromAttribute(t,s){let i=t;switch(s){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t);}catch(t){i=null;}}return i}},f$1=(t,s)=>!i$2(t,s),b$1={attribute:true,type:String,converter:u$1,reflect:false,useDefault:false,hasChanged:f$1};Symbol.metadata??=Symbol("metadata"),a$1.litPropertyMetadata??=new WeakMap;let y$1 = class y extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t);}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,s=b$1){if(s.state&&(s.attribute=false),this._$Ei(),this.prototype.hasOwnProperty(t)&&((s=Object.create(s)).wrapped=true),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),h=this.getPropertyDescriptor(t,i,s);void 0!==h&&e$1(this.prototype,t,h);}}static getPropertyDescriptor(t,s,i){const{get:e,set:r}=h$1(this.prototype,t)??{get(){return this[s]},set(t){this[s]=t;}};return {get:e,set(s){const h=e?.call(this);r?.call(this,s),this.requestUpdate(t,h,i);},configurable:true,enumerable:true}}static getPropertyOptions(t){return this.elementProperties.get(t)??b$1}static _$Ei(){if(this.hasOwnProperty(d$1("elementProperties")))return;const t=n$1(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties);}static finalize(){if(this.hasOwnProperty(d$1("finalized")))return;if(this.finalized=true,this._$Ei(),this.hasOwnProperty(d$1("properties"))){const t=this.properties,s=[...r$1(t),...o$2(t)];for(const i of s)this.createProperty(i,t[i]);}const t=this[Symbol.metadata];if(null!==t){const s=litPropertyMetadata.get(t);if(void 0!==s)for(const[t,i]of s)this.elementProperties.set(t,i);}this._$Eh=new Map;for(const[t,s]of this.elementProperties){const i=this._$Eu(t,s);void 0!==i&&this._$Eh.set(i,t);}this.elementStyles=this.finalizeStyles(this.styles);}static finalizeStyles(s){const i=[];if(Array.isArray(s)){const e=new Set(s.flat(1/0).reverse());for(const s of e)i.unshift(c$2(s));}else void 0!==s&&i.push(c$2(s));return i}static _$Eu(t,s){const i=s.attribute;return false===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=false,this.hasUpdated=false,this._$Em=null,this._$Ev();}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this));}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.();}removeController(t){this._$EO?.delete(t);}_$E_(){const t=new Map,s=this.constructor.elementProperties;for(const i of s.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t);}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return S$1(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(true),this._$EO?.forEach(t=>t.hostConnected?.());}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.());}attributeChangedCallback(t,s,i){this._$AK(t,i);}_$ET(t,s){const i=this.constructor.elementProperties.get(t),e=this.constructor._$Eu(t,i);if(void 0!==e&&true===i.reflect){const h=(void 0!==i.converter?.toAttribute?i.converter:u$1).toAttribute(s,i.type);this._$Em=t,null==h?this.removeAttribute(e):this.setAttribute(e,h),this._$Em=null;}}_$AK(t,s){const i=this.constructor,e=i._$Eh.get(t);if(void 0!==e&&this._$Em!==e){const t=i.getPropertyOptions(e),h="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:u$1;this._$Em=e;const r=h.fromAttribute(s,t.type);this[e]=r??this._$Ej?.get(e)??r,this._$Em=null;}}requestUpdate(t,s,i,e=false,h){if(void 0!==t){const r=this.constructor;if(false===e&&(h=this[t]),i??=r.getPropertyOptions(t),!((i.hasChanged??f$1)(h,s)||i.useDefault&&i.reflect&&h===this._$Ej?.get(t)&&!this.hasAttribute(r._$Eu(t,i))))return;this.C(t,s,i);} false===this.isUpdatePending&&(this._$ES=this._$EP());}C(t,s,{useDefault:i,reflect:e,wrapped:h},r){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??s??this[t]),true!==h||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||i||(s=void 0),this._$AL.set(t,s)),true===e&&this._$Em!==t&&(this._$Eq??=new Set).add(t));}async _$EP(){this.isUpdatePending=true;try{await this._$ES;}catch(t){Promise.reject(t);}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,s]of this._$Ep)this[t]=s;this._$Ep=void 0;}const t=this.constructor.elementProperties;if(t.size>0)for(const[s,i]of t){const{wrapped:t}=i,e=this[s];true!==t||this._$AL.has(s)||void 0===e||this.C(s,void 0,i,e);}}let t=false;const s=this._$AL;try{t=this.shouldUpdate(s),t?(this.willUpdate(s),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(s)):this._$EM();}catch(s){throw t=false,this._$EM(),s}t&&this._$AE(s);}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=true,this.firstUpdated(t)),this.updated(t);}_$EM(){this._$AL=new Map,this.isUpdatePending=false;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return true}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM();}updated(t){}firstUpdated(t){}};y$1.elementStyles=[],y$1.shadowRootOptions={mode:"open"},y$1[d$1("elementProperties")]=new Map,y$1[d$1("finalized")]=new Map,p$1?.({ReactiveElement:y$1}),(a$1.reactiveElementVersions??=[]).push("2.1.2");
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @license
|
|
99
|
+
* Copyright 2017 Google LLC
|
|
100
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
101
|
+
*/
|
|
102
|
+
const t=globalThis,i$1=t=>t,s$1=t.trustedTypes,e=s$1?s$1.createPolicy("lit-html",{createHTML:t=>t}):void 0,h="$lit$",o$1=`lit$${Math.random().toFixed(9).slice(2)}$`,n="?"+o$1,r=`<${n}>`,l=document,c=()=>l.createComment(""),a=t=>null===t||"object"!=typeof t&&"function"!=typeof t,u=Array.isArray,d=t=>u(t)||"function"==typeof t?.[Symbol.iterator],f="[ \t\n\f\r]",v=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,_=/-->/g,m=/>/g,p=RegExp(`>|${f}(?:([^\\s"'>=/]+)(${f}*=${f}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),g=/'/g,$=/"/g,y=/^(?:script|style|textarea|title)$/i,x=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),b=x(1),E=Symbol.for("lit-noChange"),A=Symbol.for("lit-nothing"),C=new WeakMap,P=l.createTreeWalker(l,129);function V(t,i){if(!u(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==e?e.createHTML(i):i}const N=(t,i)=>{const s=t.length-1,e=[];let n,l=2===i?"<svg>":3===i?"<math>":"",c=v;for(let i=0;i<s;i++){const s=t[i];let a,u,d=-1,f=0;for(;f<s.length&&(c.lastIndex=f,u=c.exec(s),null!==u);)f=c.lastIndex,c===v?"!--"===u[1]?c=_:void 0!==u[1]?c=m:void 0!==u[2]?(y.test(u[2])&&(n=RegExp("</"+u[2],"g")),c=p):void 0!==u[3]&&(c=p):c===p?">"===u[0]?(c=n??v,d=-1):void 0===u[1]?d=-2:(d=c.lastIndex-u[2].length,a=u[1],c=void 0===u[3]?p:'"'===u[3]?$:g):c===$||c===g?c=p:c===_||c===m?c=v:(c=p,n=void 0);const x=c===p&&t[i+1].startsWith("/>")?" ":"";l+=c===v?s+r:d>=0?(e.push(a),s.slice(0,d)+h+s.slice(d)+o$1+x):s+o$1+(-2===d?i:x);}return [V(t,l+(t[s]||"<?>")+(2===i?"</svg>":3===i?"</math>":"")),e]};class S{constructor({strings:t,_$litType$:i},e){let r;this.parts=[];let l=0,a=0;const u=t.length-1,d=this.parts,[f,v]=N(t,i);if(this.el=S.createElement(f,e),P.currentNode=this.el.content,2===i||3===i){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes);}for(;null!==(r=P.nextNode())&&d.length<u;){if(1===r.nodeType){if(r.hasAttributes())for(const t of r.getAttributeNames())if(t.endsWith(h)){const i=v[a++],s=r.getAttribute(t).split(o$1),e=/([.?@])?(.*)/.exec(i);d.push({type:1,index:l,name:e[2],strings:s,ctor:"."===e[1]?I:"?"===e[1]?L:"@"===e[1]?z:H}),r.removeAttribute(t);}else t.startsWith(o$1)&&(d.push({type:6,index:l}),r.removeAttribute(t));if(y.test(r.tagName)){const t=r.textContent.split(o$1),i=t.length-1;if(i>0){r.textContent=s$1?s$1.emptyScript:"";for(let s=0;s<i;s++)r.append(t[s],c()),P.nextNode(),d.push({type:2,index:++l});r.append(t[i],c());}}}else if(8===r.nodeType)if(r.data===n)d.push({type:2,index:l});else {let t=-1;for(;-1!==(t=r.data.indexOf(o$1,t+1));)d.push({type:7,index:l}),t+=o$1.length-1;}l++;}}static createElement(t,i){const s=l.createElement("template");return s.innerHTML=t,s}}function M(t,i,s=t,e){if(i===E)return i;let h=void 0!==e?s._$Co?.[e]:s._$Cl;const o=a(i)?void 0:i._$litDirective$;return h?.constructor!==o&&(h?._$AO?.(false),void 0===o?h=void 0:(h=new o(t),h._$AT(t,s,e)),void 0!==e?(s._$Co??=[])[e]=h:s._$Cl=h),void 0!==h&&(i=M(t,h._$AS(t,i.values),h,e)),i}class R{constructor(t,i){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=i;}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:i},parts:s}=this._$AD,e=(t?.creationScope??l).importNode(i,true);P.currentNode=e;let h=P.nextNode(),o=0,n=0,r=s[0];for(;void 0!==r;){if(o===r.index){let i;2===r.type?i=new k(h,h.nextSibling,this,t):1===r.type?i=new r.ctor(h,r.name,r.strings,this,t):6===r.type&&(i=new Z(h,this,t)),this._$AV.push(i),r=s[++n];}o!==r?.index&&(h=P.nextNode(),o++);}return P.currentNode=l,e}p(t){let i=0;for(const s of this._$AV) void 0!==s&&(void 0!==s.strings?(s._$AI(t,s,i),i+=s.strings.length-2):s._$AI(t[i])),i++;}}class k{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,i,s,e){this.type=2,this._$AH=A,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this._$Cv=e?.isConnected??true;}get parentNode(){let t=this._$AA.parentNode;const i=this._$AM;return void 0!==i&&11===t?.nodeType&&(t=i.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,i=this){t=M(this,t,i),a(t)?t===A||null==t||""===t?(this._$AH!==A&&this._$AR(),this._$AH=A):t!==this._$AH&&t!==E&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):d(t)?this.k(t):this._(t);}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t));}_(t){this._$AH!==A&&a(this._$AH)?this._$AA.nextSibling.data=t:this.T(l.createTextNode(t)),this._$AH=t;}$(t){const{values:i,_$litType$:s}=t,e="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=S.createElement(V(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===e)this._$AH.p(i);else {const t=new R(e,this),s=t.u(this.options);t.p(i),this.T(s),this._$AH=t;}}_$AC(t){let i=C.get(t.strings);return void 0===i&&C.set(t.strings,i=new S(t)),i}k(t){u(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,e=0;for(const h of t)e===i.length?i.push(s=new k(this.O(c()),this.O(c()),this,this.options)):s=i[e],s._$AI(h),e++;e<i.length&&(this._$AR(s&&s._$AB.nextSibling,e),i.length=e);}_$AR(t=this._$AA.nextSibling,s){for(this._$AP?.(false,true,s);t!==this._$AB;){const s=i$1(t).nextSibling;i$1(t).remove(),t=s;}}setConnected(t){ void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t));}}class H{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,i,s,e,h){this.type=1,this._$AH=A,this._$AN=void 0,this.element=t,this.name=i,this._$AM=e,this.options=h,s.length>2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=A;}_$AI(t,i=this,s,e){const h=this.strings;let o=false;if(void 0===h)t=M(this,t,i,0),o=!a(t)||t!==this._$AH&&t!==E,o&&(this._$AH=t);else {const e=t;let n,r;for(t=h[0],n=0;n<h.length-1;n++)r=M(this,e[s+n],i,n),r===E&&(r=this._$AH[n]),o||=!a(r)||r!==this._$AH[n],r===A?t=A:t!==A&&(t+=(r??"")+h[n+1]),this._$AH[n]=r;}o&&!e&&this.j(t);}j(t){t===A?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"");}}class I extends H{constructor(){super(...arguments),this.type=3;}j(t){this.element[this.name]=t===A?void 0:t;}}class L extends H{constructor(){super(...arguments),this.type=4;}j(t){this.element.toggleAttribute(this.name,!!t&&t!==A);}}class z extends H{constructor(t,i,s,e,h){super(t,i,s,e,h),this.type=5;}_$AI(t,i=this){if((t=M(this,t,i,0)??A)===E)return;const s=this._$AH,e=t===A&&s!==A||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,h=t!==A&&(s===A||e);e&&this.element.removeEventListener(this.name,this,s),h&&this.element.addEventListener(this.name,this,t),this._$AH=t;}handleEvent(t){"function"==typeof this._$AH?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t);}}class Z{constructor(t,i,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=i,this.options=s;}get _$AU(){return this._$AM._$AU}_$AI(t){M(this,t);}}const B=t.litHtmlPolyfillSupport;B?.(S,k),(t.litHtmlVersions??=[]).push("3.3.2");const D=(t,i,s)=>{const e=s?.renderBefore??i;let h=e._$litPart$;if(void 0===h){const t=s?.renderBefore??null;e._$litPart$=h=new k(i.insertBefore(c(),t),t,void 0,s??{});}return h._$AI(t),h};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @license
|
|
106
|
+
* Copyright 2017 Google LLC
|
|
107
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
108
|
+
*/const s=globalThis;class i extends y$1{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0;}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const r=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=D(r,this.renderRoot,this.renderOptions);}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(true);}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(false);}render(){return E}}i._$litElement$=true,i["finalized"]=true,s.litElementHydrateSupport?.({LitElement:i});const o=s.litElementPolyfillSupport;o?.({LitElement:i});(s.litElementVersions??=[]).push("4.2.2");
|
|
109
|
+
|
|
110
|
+
// Copyright (c) 2020 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
111
|
+
// See LICENSE in the project root for license information.
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
const ISO_8601_REGEX =
|
|
115
|
+
/^(\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?)?)(Z|[+-]\d{2}:\d{2})?$/u;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Shows a date or time as text, formatted for a language and region you choose and, optionally, a specific time zone.
|
|
119
|
+
*
|
|
120
|
+
* **Key capabilities**
|
|
121
|
+
* - **What to show**: `type` picks the full date, the time, a numeric date, or a single part, such as the year or weekday.
|
|
122
|
+
* - **Date and time to show**: `value` takes an ISO 8601 date or date-time; without it, the element shows the current date and time.
|
|
123
|
+
* - **Language formatting**: `locale` formats month names, separators, and the 12- or 24-hour clock for a language, such as `de-DE`.
|
|
124
|
+
* - **Time zones**: `timezone` shows the moment in a time zone, such as `America/Los_Angeles`.
|
|
125
|
+
* - **Name length**: `month="long"` and `weekday="long"` spell out the month and weekday names.
|
|
126
|
+
*
|
|
127
|
+
* **Example**
|
|
128
|
+
* ```html
|
|
129
|
+
* <auro-datetime type="date" value="2022-07-14T08:00:00"></auro-datetime>
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* @summary Date or time text formatted by language and time zone, with full, numeric, and single-part formats.
|
|
133
|
+
* @customElement auro-datetime
|
|
134
|
+
*
|
|
135
|
+
* @slot pre - Content shown before the date or time, such as "Departs". The element doesn't currently let content sit right against the date or time: this content, or text right before the element, always shows with a space between it and the date or time. {@category ui}
|
|
136
|
+
* @slot post - Content shown after the date or time, such as "local time". The element doesn't currently let content sit right against the date or time: this content, or text right after the element, always shows with a space between them, so a period or comma can't follow the date or time directly. {@category ui}
|
|
137
|
+
* @slot - Content shown after the `post` slot's content, such as the end of a sentence that includes the date. {@category ui}
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
class AuroDatetime extends i {
|
|
141
|
+
constructor() {
|
|
142
|
+
super();
|
|
143
|
+
|
|
144
|
+
this._initializeDefaults();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Sets the element's default values.
|
|
149
|
+
* @private
|
|
150
|
+
* @returns {void}
|
|
151
|
+
*/
|
|
152
|
+
_initializeDefaults() {
|
|
153
|
+
this.weekday = "short";
|
|
154
|
+
this.month = "short";
|
|
155
|
+
this.locale = "en-US";
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Tracks invalid locale inputs already warned about, so a parent that
|
|
159
|
+
* re-renders with the same bad value doesn't flood the console.
|
|
160
|
+
* @private
|
|
161
|
+
*/
|
|
162
|
+
this._warnedLocales = new Set();
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Tracks invalid `timezone` values this element has already warned
|
|
166
|
+
* about, so the same bad value logs only one warning.
|
|
167
|
+
* @private
|
|
168
|
+
*/
|
|
169
|
+
this._warnedTimeZones = new Set();
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Tracks invalid `value` inputs this element has already warned about,
|
|
173
|
+
* so the same bad value logs only one warning.
|
|
174
|
+
* @private
|
|
175
|
+
*/
|
|
176
|
+
this._warnedValues = new Set();
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @private
|
|
180
|
+
*/
|
|
181
|
+
this._effectiveLocale = this._resolveLocale(this.locale);
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* @private
|
|
185
|
+
*/
|
|
186
|
+
this._effectiveTimeZone = this._resolveTimeZone(this.timezone);
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @private
|
|
190
|
+
*/
|
|
191
|
+
this.runtimeUtils = new AuroLibraryRuntimeUtils();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Checks a BCP 47 locale tag and returns its canonical form. Empty or invalid
|
|
196
|
+
* input falls back to "en-US". Each invalid value logs a console warning the
|
|
197
|
+
* first time this element sees it.
|
|
198
|
+
*
|
|
199
|
+
* @private
|
|
200
|
+
* @param {string} input - The locale tag set on the element.
|
|
201
|
+
* @returns {string} The canonical locale tag, such as "en-GB", or "en-US" for empty or invalid input.
|
|
202
|
+
*/
|
|
203
|
+
_resolveLocale(input) {
|
|
204
|
+
if (!input) {
|
|
205
|
+
return "en-US";
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
return Intl.getCanonicalLocales(input)[0];
|
|
209
|
+
} catch {
|
|
210
|
+
if (this._warnedLocales && !this._warnedLocales.has(input)) {
|
|
211
|
+
this._warnedLocales.add(input);
|
|
212
|
+
console.warn(
|
|
213
|
+
`auro-datetime: "${input}" is not a valid BCP 47 locale tag. Falling back to "en-US".`,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
return "en-US";
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Checks an IANA time zone name. An invalid name logs a console warning
|
|
222
|
+
* the first time this element sees it and returns `undefined`, so the
|
|
223
|
+
* element acts as if `timezone` isn't set.
|
|
224
|
+
*
|
|
225
|
+
* @private
|
|
226
|
+
* @param {string | undefined} input - The time zone name set on the element.
|
|
227
|
+
* @returns {string | undefined} The time zone name if it's valid; otherwise, `undefined`.
|
|
228
|
+
*/
|
|
229
|
+
_resolveTimeZone(input) {
|
|
230
|
+
if (!input) {
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
try {
|
|
234
|
+
// Creating the formatter is enough to catch an invalid name. Without
|
|
235
|
+
// this check, a typo such as "America/Los_Angles" makes
|
|
236
|
+
// Intl.DateTimeFormat and toLocaleString throw a RangeError at render
|
|
237
|
+
// time.
|
|
238
|
+
new Intl.DateTimeFormat(undefined, { timeZone: input });
|
|
239
|
+
return input;
|
|
240
|
+
} catch {
|
|
241
|
+
if (this._warnedTimeZones && !this._warnedTimeZones.has(input)) {
|
|
242
|
+
this._warnedTimeZones.add(input);
|
|
243
|
+
console.warn(
|
|
244
|
+
`auro-datetime: "${input}" is not a valid IANA timezone. Ignoring it.`,
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
static get properties() {
|
|
252
|
+
return {
|
|
253
|
+
/**
|
|
254
|
+
* Sets the language and region used to format the date or time, such as `en-GB`, `de-DE`, or `ja-JP` (a BCP 47 language tag). It changes month and weekday names, separators, and whether times use a 12- or 24-hour clock, but not the time zone. A malformed tag logs a console warning and falls back to `en-US`; a well-formed tag the browser doesn't support, such as `zz-ZZ`, uses the browser's default language instead, with no warning.
|
|
255
|
+
* @type {string}
|
|
256
|
+
* @default "en-US"
|
|
257
|
+
* @category ui
|
|
258
|
+
*/
|
|
259
|
+
locale: { type: String },
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Sets how the month name is written: `short`, such as "Jul", or `long`, such as "July". It applies to the full date and to `type="month"`.
|
|
263
|
+
* @type {"short" | "long"}
|
|
264
|
+
* @default "short"
|
|
265
|
+
* @category ui
|
|
266
|
+
*/
|
|
267
|
+
month: { type: String },
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Sets the time zone to show the date or time in, such as `America/Los_Angeles` or `UTC` (an IANA time zone name). When `value` has an offset or `Z`, the element converts that moment into this zone; when it has none, the element reads `value` as a time already in this zone. Without it, or with an invalid name, which logs a console warning, the element shows the date and time in `value` as written, or the current date and time in the viewer's own time zone when `value` isn't set.
|
|
271
|
+
* @type {string}
|
|
272
|
+
* @category behavior
|
|
273
|
+
*/
|
|
274
|
+
timezone: { type: String },
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Sets which part of the date or time to show: `date` for the full date, such as "Thu, Jul 14, 2022", `numeric` for a numeric date, such as "7/14/2022", `time` for the hour and minute, such as "8:00 am", or `year`, `month`, `weekday`, or `day` for that part alone. Without it, or with any other value, the element shows the full date.
|
|
278
|
+
* @type {"date" | "time" | "year" | "month" | "weekday" | "day" | "numeric"}
|
|
279
|
+
* @category ui
|
|
280
|
+
*/
|
|
281
|
+
type: { type: String },
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Sets the date or time to show, as an ISO 8601 date or date-time, such as `2022-07-14`, `2022-07-14T08:00:00`, or `2022-07-14T08:00:00-07:00`. Without it, the element shows the current date and time from when it last rendered; it doesn't currently update as time passes. Invalid input, including an empty value, logs a console warning and shows nothing.
|
|
285
|
+
* @type {string}
|
|
286
|
+
* @category behavior
|
|
287
|
+
*/
|
|
288
|
+
value: { type: String },
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Sets how the weekday name is written: `short`, such as "Thu", or `long`, such as "Thursday". It applies to the full date and to `type="weekday"`.
|
|
292
|
+
* @type {"short" | "long"}
|
|
293
|
+
* @default "short"
|
|
294
|
+
* @category ui
|
|
295
|
+
*/
|
|
296
|
+
weekday: { type: String },
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Registers the element with the browser under a tag name. Use a custom name to run more than one version of the element on the same page. If the tag name is already registered, it does nothing.
|
|
302
|
+
* @param {string} [name="auro-datetime"] - The tag name to register the element under, such as `custom-datetime`.
|
|
303
|
+
* @returns {void}
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* AuroDatetime.register("custom-datetime"); // registers <custom-datetime>
|
|
307
|
+
*/
|
|
308
|
+
static register(name = "auro-datetime") {
|
|
309
|
+
AuroLibraryRuntimeUtils.prototype.registerComponent(name, AuroDatetime);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
willUpdate(changedProperties) {
|
|
313
|
+
if (changedProperties.has("locale")) {
|
|
314
|
+
this._effectiveLocale = this._resolveLocale(this.locale);
|
|
315
|
+
}
|
|
316
|
+
if (changedProperties.has("timezone")) {
|
|
317
|
+
this._effectiveTimeZone = this._resolveTimeZone(this.timezone);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
firstUpdated() {
|
|
322
|
+
// Adds the tag name as an attribute when it differs from auro-datetime.
|
|
323
|
+
this.runtimeUtils.handleComponentTagRename(this, "auro-datetime");
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Creates a Date that shows the given wall-clock time when displayed in
|
|
328
|
+
* the given IANA time zone. `_resolveInputDate` uses it when `value` has
|
|
329
|
+
* no offset and `timezone` is set, so the time is read as already being
|
|
330
|
+
* in that zone rather than the viewer's.
|
|
331
|
+
*
|
|
332
|
+
* It parses the wall-clock time as if it were UTC, asks `Intl` what that
|
|
333
|
+
* moment looks like in the target zone, and uses the difference between
|
|
334
|
+
* the two to find the real moment.
|
|
335
|
+
*
|
|
336
|
+
* @private
|
|
337
|
+
* @param {string} localISO - The ISO 8601 date-time with no offset, such as "2022-07-14T08:00:00".
|
|
338
|
+
* @param {string} timeZone - The IANA time zone name, such as "America/New_York".
|
|
339
|
+
* @returns {Date} The moment that reads as `localISO` in `timeZone`.
|
|
340
|
+
*/
|
|
341
|
+
_zonedWallClockToUtc(localISO, timeZone) {
|
|
342
|
+
const naiveUtc = new Date(`${localISO}Z`);
|
|
343
|
+
const parts = new Intl.DateTimeFormat("en-US", {
|
|
344
|
+
timeZone,
|
|
345
|
+
hourCycle: "h23",
|
|
346
|
+
year: "numeric",
|
|
347
|
+
month: "2-digit",
|
|
348
|
+
day: "2-digit",
|
|
349
|
+
hour: "2-digit",
|
|
350
|
+
minute: "2-digit",
|
|
351
|
+
second: "2-digit",
|
|
352
|
+
}).formatToParts(naiveUtc);
|
|
353
|
+
const lookup = Object.fromEntries(
|
|
354
|
+
parts.filter((p) => p.type !== "literal").map((p) => [p.type, p.value]),
|
|
355
|
+
);
|
|
356
|
+
const seenInZone = new Date(
|
|
357
|
+
`${lookup.year}-${lookup.month}-${lookup.day}T${lookup.hour}:${lookup.minute}:${lookup.second}Z`,
|
|
358
|
+
);
|
|
359
|
+
const offsetMs = naiveUtc.getTime() - seenInZone.getTime();
|
|
360
|
+
return new Date(naiveUtc.getTime() + offsetMs);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Gets the Date to show and the `timeZone` option for `Intl.DateTimeFormat`,
|
|
365
|
+
* from `value` and `timezone`. Returns `{ date: null }` for invalid input,
|
|
366
|
+
* including an empty string.
|
|
367
|
+
*
|
|
368
|
+
* @private
|
|
369
|
+
* @returns {{ date: Date | null, timeZoneOption: string | undefined }} The Date to show, or `null` for invalid input, and the `timeZone` option to format it with.
|
|
370
|
+
*/
|
|
371
|
+
_resolveInputDate() {
|
|
372
|
+
// How each case resolves:
|
|
373
|
+
// - `value` not set (null or undefined): the current date and time, in
|
|
374
|
+
// `timezone` if it's set.
|
|
375
|
+
// - `value` invalid, including an empty string: logs a warning and
|
|
376
|
+
// returns { date: null }. An empty string isn't the same as not set:
|
|
377
|
+
// Lit gives value="" as an empty string, which isn't valid ISO 8601,
|
|
378
|
+
// so it's reported as a likely mistake instead of showing the
|
|
379
|
+
// current date.
|
|
380
|
+
// - `timezone` set and `value` has an offset or Z: reads `value` as an
|
|
381
|
+
// exact moment and has toLocaleString convert it into `timezone`.
|
|
382
|
+
// - `timezone` set and `value` has no offset: reads `value` as a time
|
|
383
|
+
// already in `timezone`, so every viewer sees it as written.
|
|
384
|
+
// - `timezone` not set: drops any offset or Z and reads the rest as
|
|
385
|
+
// local time, so it shows as written.
|
|
386
|
+
const resolvedTz = this._effectiveTimeZone;
|
|
387
|
+
|
|
388
|
+
// Only true "omitted" inputs (null/undefined) get the current-date
|
|
389
|
+
// treatment. Empty string falls through to ISO validation, which
|
|
390
|
+
// fails and produces the documented warning and empty output.
|
|
391
|
+
if (this.value == null) {
|
|
392
|
+
return { date: new Date(), timeZoneOption: resolvedTz };
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const match = this.value.match(ISO_8601_REGEX);
|
|
396
|
+
if (!match) {
|
|
397
|
+
if (!this._warnedValues.has(this.value)) {
|
|
398
|
+
this._warnedValues.add(this.value);
|
|
399
|
+
console.warn(
|
|
400
|
+
`auro-datetime: "${this.value}" is not a valid ISO 8601 string.`,
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
return { date: null, timeZoneOption: undefined };
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const localPart = match[1];
|
|
407
|
+
const hasOffset = Boolean(match[2]);
|
|
408
|
+
|
|
409
|
+
// The regex permits an offset/Z suffix on a bare date (such as "2020-09-22Z"
|
|
410
|
+
// or "2020-09-22-07:00"). Those forms are not valid ISO 8601: an offset
|
|
411
|
+
// is only meaningful with a time component, and the wall-clock branch
|
|
412
|
+
// would silently drop the offset, producing surprising output. Reject
|
|
413
|
+
// them up front so the consumer sees a warning.
|
|
414
|
+
if (hasOffset && !localPart.includes("T")) {
|
|
415
|
+
if (!this._warnedValues.has(this.value)) {
|
|
416
|
+
this._warnedValues.add(this.value);
|
|
417
|
+
console.warn(
|
|
418
|
+
`auro-datetime: "${this.value}" is not a valid ISO 8601 string (offset/Z requires a time component).`,
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
return { date: null, timeZoneOption: undefined };
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const normalized = localPart.includes("T")
|
|
425
|
+
? localPart
|
|
426
|
+
: `${localPart}T00:00:00`;
|
|
427
|
+
|
|
428
|
+
// The regex only validates string shape, not value ranges: "2022-99-99"
|
|
429
|
+
// matches but produces an Invalid Date. Detect that and treat it like
|
|
430
|
+
// any other malformed input so render falls back to the documented
|
|
431
|
+
// empty output instead of "Invalid Date" or a thrown RangeError from
|
|
432
|
+
// downstream Intl calls.
|
|
433
|
+
const buildDate = () => {
|
|
434
|
+
if (resolvedTz && !hasOffset) {
|
|
435
|
+
return this._zonedWallClockToUtc(normalized, resolvedTz);
|
|
436
|
+
}
|
|
437
|
+
if (resolvedTz && hasOffset) {
|
|
438
|
+
return new Date(this.value);
|
|
439
|
+
}
|
|
440
|
+
// Wall-clock: keep the components in the input verbatim. JS parses
|
|
441
|
+
// bare "YYYY-MM-DD" as UTC midnight, which shifts the date in the
|
|
442
|
+
// viewer's timezone; appending a time forces local-time parsing.
|
|
443
|
+
return new Date(normalized);
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
const date = buildDate();
|
|
447
|
+
if (Number.isNaN(date.getTime())) {
|
|
448
|
+
if (!this._warnedValues.has(this.value)) {
|
|
449
|
+
this._warnedValues.add(this.value);
|
|
450
|
+
console.warn(
|
|
451
|
+
`auro-datetime: "${this.value}" is not a valid ISO 8601 date.`,
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
return { date: null, timeZoneOption: undefined };
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return { date, timeZoneOption: resolvedTz };
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Formats the full date, such as "Thu, Jul 14, 2022", with the current `month` and `weekday` settings.
|
|
462
|
+
* @private
|
|
463
|
+
* @returns {string} The formatted date, or an empty string when `value` is invalid.
|
|
464
|
+
*/
|
|
465
|
+
humanDate() {
|
|
466
|
+
const { date, timeZoneOption } = this._resolveInputDate();
|
|
467
|
+
if (!date) {
|
|
468
|
+
return "";
|
|
469
|
+
}
|
|
470
|
+
// Read month and weekday on every render so later changes show up.
|
|
471
|
+
const template = {
|
|
472
|
+
weekday: this.weekday || "short",
|
|
473
|
+
year: "numeric",
|
|
474
|
+
month: this.month || "short",
|
|
475
|
+
day: "numeric",
|
|
476
|
+
};
|
|
477
|
+
if (timeZoneOption) {
|
|
478
|
+
template.timeZone = timeZoneOption;
|
|
479
|
+
}
|
|
480
|
+
return date.toLocaleString(this._effectiveLocale, template);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Formats the single date part that `type` names: the year, month, weekday, or day.
|
|
485
|
+
* @private
|
|
486
|
+
* @returns {string} The formatted date, or an empty string when `value` is invalid.
|
|
487
|
+
*/
|
|
488
|
+
humanDateConversion() {
|
|
489
|
+
const { date, timeZoneOption } = this._resolveInputDate();
|
|
490
|
+
if (!date) {
|
|
491
|
+
return "";
|
|
492
|
+
}
|
|
493
|
+
const template = {};
|
|
494
|
+
if (timeZoneOption) {
|
|
495
|
+
template.timeZone = timeZoneOption;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
switch (this.type) {
|
|
499
|
+
case "day":
|
|
500
|
+
template.day = "numeric";
|
|
501
|
+
break;
|
|
502
|
+
case "month":
|
|
503
|
+
template.month = this.month || "short";
|
|
504
|
+
break;
|
|
505
|
+
case "year":
|
|
506
|
+
template.year = "numeric";
|
|
507
|
+
break;
|
|
508
|
+
case "weekday":
|
|
509
|
+
template.weekday = this.weekday || "short";
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
return date.toLocaleString(this._effectiveLocale, template);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Formats the date in numbers, in the order and with the separators `locale` uses, such as "7/14/2022" for `en-US`.
|
|
518
|
+
* @private
|
|
519
|
+
* @returns {string} The formatted date, or an empty string when `value` is invalid.
|
|
520
|
+
*/
|
|
521
|
+
numericDate() {
|
|
522
|
+
const { date, timeZoneOption } = this._resolveInputDate();
|
|
523
|
+
if (!date) {
|
|
524
|
+
return "";
|
|
525
|
+
}
|
|
526
|
+
const template = { year: "numeric", month: "numeric", day: "numeric" };
|
|
527
|
+
if (timeZoneOption) {
|
|
528
|
+
template.timeZone = timeZoneOption;
|
|
529
|
+
}
|
|
530
|
+
return date.toLocaleString(this._effectiveLocale, template);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Formats the hour and minute. When the time ends in AM or PM, it lowercases the period and drops a leading zero.
|
|
535
|
+
* @private
|
|
536
|
+
* @returns {string} The formatted time, or an empty string when `value` is invalid.
|
|
537
|
+
*/
|
|
538
|
+
humanTime() {
|
|
539
|
+
const { date, timeZoneOption } = this._resolveInputDate();
|
|
540
|
+
if (!date) {
|
|
541
|
+
return "";
|
|
542
|
+
}
|
|
543
|
+
const template = { hour: "2-digit", minute: "2-digit" };
|
|
544
|
+
if (timeZoneOption) {
|
|
545
|
+
template.timeZone = timeZoneOption;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const formatted = date.toLocaleString(this._effectiveLocale, template);
|
|
549
|
+
|
|
550
|
+
// Detect a 12-hour rendered output by the presence of a Latin-script
|
|
551
|
+
// period marker. The pattern matches `am`, `pm`, `a.m.`, `p.m.`
|
|
552
|
+
// (case-insensitive), so it catches en-US (`PM`), en-AU/hi-IN (`pm`),
|
|
553
|
+
// and en-CA/es-MX (`p.m.`) alike. Non-Latin period markers (ko `오후`,
|
|
554
|
+
// ar `م`, zh-TW `下午`) have no ASCII a/p+m chars and correctly fall
|
|
555
|
+
// through unchanged. 24h locales (en-GB, de-DE, fr-FR, ja-JP, and
|
|
556
|
+
// others) also fall through, preserving their leading zeros.
|
|
557
|
+
if (!/[ap]\.?m\.?/iu.test(formatted)) {
|
|
558
|
+
return formatted;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return formatted.replace(/^0+/u, "").toLowerCase();
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Gets the text to show for the current `type`.
|
|
566
|
+
* @private
|
|
567
|
+
* @returns {string} The formatted text; the full date when `type` isn't set or isn't recognized.
|
|
568
|
+
*/
|
|
569
|
+
whichDate() {
|
|
570
|
+
switch (this.type) {
|
|
571
|
+
case "date":
|
|
572
|
+
return this.humanDate();
|
|
573
|
+
case "time":
|
|
574
|
+
return this.humanTime();
|
|
575
|
+
case "year":
|
|
576
|
+
case "month":
|
|
577
|
+
case "weekday":
|
|
578
|
+
case "day":
|
|
579
|
+
return this.humanDateConversion();
|
|
580
|
+
case "numeric":
|
|
581
|
+
return this.numericDate();
|
|
582
|
+
default:
|
|
583
|
+
return this.humanDate();
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
render() {
|
|
588
|
+
return b`
|
|
589
|
+
<slot name="pre"></slot>
|
|
590
|
+
<span class="yield">${this.whichDate()}</span>
|
|
591
|
+
<slot name="post"></slot>
|
|
592
|
+
<slot></slot>
|
|
593
|
+
`;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
2
596
|
|
|
3
597
|
/* eslint-disable jsdoc/require-jsdoc, no-magic-numbers, no-param-reassign */
|
|
4
598
|
|