urnovl-web-components 0.0.59 → 0.0.60
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/dist/cjs/button-base-f4219018.js +3423 -0
- package/dist/{urnovl-web-components/p-4c272cd5.entry.js.map → cjs/button-base-f4219018.js.map} +1 -1
- package/dist/cjs/ur-button-arrow-left_2.cjs.entry.js +166 -4
- package/dist/cjs/ur-button-arrow-left_2.cjs.entry.js.map +1 -1
- package/dist/cjs/ur-profile.cjs.entry.js +25 -3432
- package/dist/cjs/ur-profile.cjs.entry.js.map +1 -1
- package/dist/collection/components/ur-button-arrow-left/ur-button-arrow-left.css +7 -1
- package/dist/collection/components/ur-button-arrow-left/ur-button-arrow-left.js +2 -1
- package/dist/collection/components/ur-button-arrow-left/ur-button-arrow-left.js.map +1 -1
- package/dist/collection/components/ur-button-arrow-right/ur-button-arrow-right.css +7 -1
- package/dist/collection/components/ur-button-arrow-right/ur-button-arrow-right.js +2 -1
- package/dist/collection/components/ur-button-arrow-right/ur-button-arrow-right.js.map +1 -1
- package/dist/collection/stories/Mdui.stories.js +0 -4
- package/dist/collection/stories/Mdui.stories.js.map +1 -1
- package/dist/collection/stories/Profile.stories.js +0 -3
- package/dist/collection/stories/Profile.stories.js.map +1 -1
- package/dist/components/p-24f4ff71.js +36 -0
- package/dist/components/p-24f4ff71.js.map +1 -0
- package/dist/components/p-291d60ec.js +164 -0
- package/dist/components/p-291d60ec.js.map +1 -0
- package/dist/components/p-a3558c16.js +36 -0
- package/dist/components/p-a3558c16.js.map +1 -0
- package/dist/components/p-aec308e7.js +3411 -0
- package/dist/components/p-aec308e7.js.map +1 -0
- package/dist/components/ur-button-arrow-left.js +1 -1
- package/dist/components/ur-button-arrow-right.js +1 -1
- package/dist/components/ur-novl-carousel.js +2 -2
- package/dist/components/ur-profile.js +9 -3416
- package/dist/components/ur-profile.js.map +1 -1
- package/dist/esm/button-base-e9b7f052.js +3411 -0
- package/dist/esm/button-base-e9b7f052.js.map +1 -0
- package/dist/esm/ur-button-arrow-left_2.entry.js +166 -4
- package/dist/esm/ur-button-arrow-left_2.entry.js.map +1 -1
- package/dist/esm/ur-profile.entry.js +9 -3416
- package/dist/esm/ur-profile.entry.js.map +1 -1
- package/dist/types/components/ur-button-arrow-left/ur-button-arrow-left.d.ts +1 -0
- package/dist/types/components/ur-button-arrow-right/ur-button-arrow-right.d.ts +1 -0
- package/dist/urnovl-web-components/p-230530b0.entry.js +4 -0
- package/dist/urnovl-web-components/p-230530b0.entry.js.map +1 -0
- package/dist/urnovl-web-components/p-44e9e715.js +92 -0
- package/dist/urnovl-web-components/p-44e9e715.js.map +1 -0
- package/dist/urnovl-web-components/p-a1ffa9fb.entry.js +4 -0
- package/dist/urnovl-web-components/p-a1ffa9fb.entry.js.map +1 -0
- package/dist/urnovl-web-components/urnovl-web-components.esm.js +1 -1
- package/package.json +1 -1
- package/dist/components/p-03108de8.js +0 -35
- package/dist/components/p-03108de8.js.map +0 -1
- package/dist/components/p-bf15a67b.js +0 -35
- package/dist/components/p-bf15a67b.js.map +0 -1
- package/dist/urnovl-web-components/p-4c272cd5.entry.js +0 -94
- package/dist/urnovl-web-components/p-ff23b233.entry.js +0 -2
- package/dist/urnovl-web-components/p-ff23b233.entry.js.map +0 -1
|
@@ -0,0 +1,3423 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/******************************************************************************
|
|
4
|
+
Copyright (c) Microsoft Corporation.
|
|
5
|
+
|
|
6
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
7
|
+
purpose with or without fee is hereby granted.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
+
***************************************************************************** */
|
|
17
|
+
|
|
18
|
+
function __decorate(decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
26
|
+
var e = new Error(message);
|
|
27
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @license
|
|
32
|
+
* Copyright 2019 Google LLC
|
|
33
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
34
|
+
*/
|
|
35
|
+
const t$2=globalThis,e$2=t$2.ShadowRoot&&(void 0===t$2.ShadyCSS||t$2.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,s=Symbol(),o$2=new WeakMap;class n$3{constructor(t,e,o){if(this._$cssResult$=!0,o!==s)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$2.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&o$2.set(s,t));}return t}toString(){return this.cssText}}const r$3=t=>new n$3("string"==typeof t?t:t+"",void 0,s),i$2=(t,...e)=>{const o=1===t.length?t[0]:e.reduce(((e,s,o)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(s)+t[o+1]),t[0]);return new n$3(o,t,s)},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$2.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$3(e)})(t):t;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @license
|
|
39
|
+
* Copyright 2017 Google LLC
|
|
40
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
41
|
+
*/const{is:i$1,defineProperty:e$1,getOwnPropertyDescriptor:r$2,getOwnPropertyNames:h$2,getOwnPropertySymbols:o$1,getPrototypeOf:n$2}=Object,a=globalThis,c$1=a.trustedTypes,l=c$1?c$1.emptyScript:"",p=a.reactiveElementPolyfillSupport,d=(t,s)=>t,u={toAttribute(t,s){switch(s){case Boolean:t=t?l: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$2=(t,s)=>!i$1(t,s),y={attribute:!0,type:String,converter:u,reflect:!1,hasChanged:f$2};Symbol.metadata??=Symbol("metadata"),a.litPropertyMetadata??=new WeakMap;class b 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=y){if(s.state&&(s.attribute=!1),this._$Ei(),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),r=this.getPropertyDescriptor(t,i,s);void 0!==r&&e$1(this.prototype,t,r);}}static getPropertyDescriptor(t,s,i){const{get:e,set:h}=r$2(this.prototype,t)??{get(){return this[s]},set(t){this[s]=t;}};return {get(){return e?.call(this)},set(s){const r=e?.call(this);h.call(this,s),this.requestUpdate(t,r,i);},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??y}static _$Ei(){if(this.hasOwnProperty(d("elementProperties")))return;const t=n$2(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties);}static finalize(){if(this.hasOwnProperty(d("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(d("properties"))){const t=this.properties,s=[...h$2(t),...o$1(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 !1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,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(!0),this._$EO?.forEach((t=>t.hostConnected?.()));}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach((t=>t.hostDisconnected?.()));}attributeChangedCallback(t,s,i){this._$AK(t,i);}_$EC(t,s){const i=this.constructor.elementProperties.get(t),e=this.constructor._$Eu(t,i);if(void 0!==e&&!0===i.reflect){const r=(void 0!==i.converter?.toAttribute?i.converter:u).toAttribute(s,i.type);this._$Em=t,null==r?this.removeAttribute(e):this.setAttribute(e,r),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),r="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:u;this._$Em=e,this[e]=r.fromAttribute(s,t.type),this._$Em=null;}}requestUpdate(t,s,i){if(void 0!==t){if(i??=this.constructor.getPropertyOptions(t),!(i.hasChanged??f$2)(this[t],s))return;this.P(t,s,i);}!1===this.isUpdatePending&&(this._$ES=this._$ET());}P(t,s,i){this._$AL.has(t)||this._$AL.set(t,s),!0===i.reflect&&this._$Em!==t&&(this._$Ej??=new Set).add(t);}async _$ET(){this.isUpdatePending=!0;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)!0!==i.wrapped||this._$AL.has(s)||void 0===this[s]||this.P(s,this[s],i);}let t=!1;const s=this._$AL;try{t=this.shouldUpdate(s),t?(this.willUpdate(s),this._$EO?.forEach((t=>t.hostUpdate?.())),this.update(s)):this._$EU();}catch(s){throw t=!1,this._$EU(),s}t&&this._$AE(s);}willUpdate(t){}_$AE(t){this._$EO?.forEach((t=>t.hostUpdated?.())),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t);}_$EU(){this._$AL=new Map,this.isUpdatePending=!1;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return !0}update(t){this._$Ej&&=this._$Ej.forEach((t=>this._$EC(t,this[t]))),this._$EU();}updated(t){}firstUpdated(t){}}b.elementStyles=[],b.shadowRootOptions={mode:"open"},b[d("elementProperties")]=new Map,b[d("finalized")]=new Map,p?.({ReactiveElement:b}),(a.reactiveElementVersions??=[]).push("2.0.4");
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @license
|
|
45
|
+
* Copyright 2017 Google LLC
|
|
46
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
47
|
+
*/
|
|
48
|
+
const n$1=globalThis,c=n$1.trustedTypes,h$1=c?c.createPolicy("lit-html",{createHTML:t=>t}):void 0,f$1="$lit$",v=`lit$${Math.random().toFixed(9).slice(2)}$`,m="?"+v,_=`<${m}>`,w=document,lt=()=>w.createComment(""),st$1=t=>null===t||"object"!=typeof t&&"function"!=typeof t,g=Array.isArray,$$1=t=>g(t)||"function"==typeof t?.[Symbol.iterator],x="[ \t\n\f\r]",T=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,E=/-->/g,k=/>/g,O=RegExp(`>|${x}(?:([^\\s"'>=/]+)(${x}*=${x}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),S=/'/g,j=/"/g,M=/^(?:script|style|textarea|title)$/i,P=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),ke=P(1),R=Symbol.for("lit-noChange"),D=Symbol.for("lit-nothing"),V=new WeakMap,I=w.createTreeWalker(w,129);function N(t,i){if(!g(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==h$1?h$1.createHTML(i):i}const U=(t,i)=>{const s=t.length-1,e=[];let h,o=2===i?"<svg>":3===i?"<math>":"",n=T;for(let i=0;i<s;i++){const s=t[i];let r,l,c=-1,a=0;for(;a<s.length&&(n.lastIndex=a,l=n.exec(s),null!==l);)a=n.lastIndex,n===T?"!--"===l[1]?n=E:void 0!==l[1]?n=k:void 0!==l[2]?(M.test(l[2])&&(h=RegExp("</"+l[2],"g")),n=O):void 0!==l[3]&&(n=O):n===O?">"===l[0]?(n=h??T,c=-1):void 0===l[1]?c=-2:(c=n.lastIndex-l[2].length,r=l[1],n=void 0===l[3]?O:'"'===l[3]?j:S):n===j||n===S?n=O:n===E||n===k?n=T:(n=O,h=void 0);const u=n===O&&t[i+1].startsWith("/>")?" ":"";o+=n===T?s+_:c>=0?(e.push(r),s.slice(0,c)+f$1+s.slice(c)+v+u):s+v+(-2===c?i:u);}return [N(t,o+(t[s]||"<?>")+(2===i?"</svg>":3===i?"</math>":"")),e]};class B{constructor({strings:t,_$litType$:i},s){let e;this.parts=[];let h=0,o=0;const n=t.length-1,r=this.parts,[l,a]=U(t,i);if(this.el=B.createElement(l,s),I.currentNode=this.el.content,2===i||3===i){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes);}for(;null!==(e=I.nextNode())&&r.length<n;){if(1===e.nodeType){if(e.hasAttributes())for(const t of e.getAttributeNames())if(t.endsWith(f$1)){const i=a[o++],s=e.getAttribute(t).split(v),n=/([.?@])?(.*)/.exec(i);r.push({type:1,index:h,name:n[2],strings:s,ctor:"."===n[1]?Y:"?"===n[1]?Z:"@"===n[1]?q:G}),e.removeAttribute(t);}else t.startsWith(v)&&(r.push({type:6,index:h}),e.removeAttribute(t));if(M.test(e.tagName)){const t=e.textContent.split(v),i=t.length-1;if(i>0){e.textContent=c?c.emptyScript:"";for(let s=0;s<i;s++)e.append(t[s],lt()),I.nextNode(),r.push({type:2,index:++h});e.append(t[i],lt());}}}else if(8===e.nodeType)if(e.data===m)r.push({type:2,index:h});else {let t=-1;for(;-1!==(t=e.data.indexOf(v,t+1));)r.push({type:7,index:h}),t+=v.length-1;}h++;}}static createElement(t,i){const s=w.createElement("template");return s.innerHTML=t,s}}function z(t,i,s=t,e){if(i===R)return i;let h=void 0!==e?s.o?.[e]:s.l;const o=st$1(i)?void 0:i._$litDirective$;return h?.constructor!==o&&(h?._$AO?.(!1),void 0===o?h=void 0:(h=new o(t),h._$AT(t,s,e)),void 0!==e?(s.o??=[])[e]=h:s.l=h),void 0!==h&&(i=z(t,h._$AS(t,i.values),h,e)),i}class F{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??w).importNode(i,!0);I.currentNode=e;let h=I.nextNode(),o=0,n=0,r=s[0];for(;void 0!==r;){if(o===r.index){let i;2===r.type?i=new et(h,h.nextSibling,this,t):1===r.type?i=new r.ctor(h,r.name,r.strings,this,t):6===r.type&&(i=new K(h,this,t)),this._$AV.push(i),r=s[++n];}o!==r?.index&&(h=I.nextNode(),o++);}return I.currentNode=w,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 et{get _$AU(){return this._$AM?._$AU??this.v}constructor(t,i,s,e){this.type=2,this._$AH=D,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this.v=e?.isConnected??!0;}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=z(this,t,i),st$1(t)?t===D||null==t||""===t?(this._$AH!==D&&this._$AR(),this._$AH=D):t!==this._$AH&&t!==R&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):$$1(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!==D&&st$1(this._$AH)?this._$AA.nextSibling.data=t:this.T(w.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=B.createElement(N(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===e)this._$AH.p(i);else {const t=new F(e,this),s=t.u(this.options);t.p(i),this.T(s),this._$AH=t;}}_$AC(t){let i=V.get(t.strings);return void 0===i&&V.set(t.strings,i=new B(t)),i}k(t){g(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 et(this.O(lt()),this.O(lt()),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,i){for(this._$AP?.(!1,!0,i);t&&t!==this._$AB;){const i=t.nextSibling;t.remove(),t=i;}}setConnected(t){void 0===this._$AM&&(this.v=t,this._$AP?.(t));}}class G{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,i,s,e,h){this.type=1,this._$AH=D,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=D;}_$AI(t,i=this,s,e){const h=this.strings;let o=!1;if(void 0===h)t=z(this,t,i,0),o=!st$1(t)||t!==this._$AH&&t!==R,o&&(this._$AH=t);else {const e=t;let n,r;for(t=h[0],n=0;n<h.length-1;n++)r=z(this,e[s+n],i,n),r===R&&(r=this._$AH[n]),o||=!st$1(r)||r!==this._$AH[n],r===D?t=D:t!==D&&(t+=(r??"")+h[n+1]),this._$AH[n]=r;}o&&!e&&this.j(t);}j(t){t===D?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"");}}class Y extends G{constructor(){super(...arguments),this.type=3;}j(t){this.element[this.name]=t===D?void 0:t;}}class Z extends G{constructor(){super(...arguments),this.type=4;}j(t){this.element.toggleAttribute(this.name,!!t&&t!==D);}}class q extends G{constructor(t,i,s,e,h){super(t,i,s,e,h),this.type=5;}_$AI(t,i=this){if((t=z(this,t,i,0)??D)===R)return;const s=this._$AH,e=t===D&&s!==D||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,h=t!==D&&(s===D||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 K{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){z(this,t);}}const Re=n$1.litHtmlPolyfillSupport;Re?.(B,et),(n$1.litHtmlVersions??=[]).push("3.2.0");const Q=(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 et(i.insertBefore(lt(),t),t,void 0,s??{});}return h._$AI(t),h};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @license
|
|
52
|
+
* Copyright 2017 Google LLC
|
|
53
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
54
|
+
*/class h extends b{constructor(){super(...arguments),this.renderOptions={host:this},this.o=void 0;}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this.o=Q(e,this.renderRoot,this.renderOptions);}connectedCallback(){super.connectedCallback(),this.o?.setConnected(!0);}disconnectedCallback(){super.disconnectedCallback(),this.o?.setConnected(!1);}render(){return R}}h._$litElement$=!0,h["finalized"]=!0,globalThis.litElementHydrateSupport?.({LitElement:h});const f=globalThis.litElementPolyfillSupport;f?.({LitElement:h});(globalThis.litElementVersions??=[]).push("4.1.0");
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @license
|
|
58
|
+
* Copyright 2017 Google LLC
|
|
59
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
60
|
+
*/
|
|
61
|
+
const t$1=t=>(e,o)=>{void 0!==o?o.addInitializer((()=>{customElements.define(t,e);})):customElements.define(t,e);};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @license
|
|
65
|
+
* Copyright 2017 Google LLC
|
|
66
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
67
|
+
*/const o={attribute:!0,type:String,converter:u,reflect:!1,hasChanged:f$2},r$1=(t=o,e,r)=>{const{kind:n,metadata:i}=r;let s=globalThis.litPropertyMetadata.get(i);if(void 0===s&&globalThis.litPropertyMetadata.set(i,s=new Map),s.set(r.name,t),"accessor"===n){const{name:o}=r;return {set(r){const n=e.get.call(this);e.set.call(this,r),this.requestUpdate(o,n,t);},init(e){return void 0!==e&&this.P(o,void 0,t),e}}}if("setter"===n){const{name:o}=r;return function(r){const n=this[o];e.call(this,r),this.requestUpdate(o,n,t);}}throw Error("Unsupported decorator location: "+n)};function n(t){return (e,o)=>"object"==typeof o?r$1(t,e,o):((t,e,o)=>{const r=e.hasOwnProperty(o);return e.constructor.createProperty(o,r?{...t,wrapped:!0}:t),r?Object.getOwnPropertyDescriptor(e,o):void 0})(t,e,o)}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @license
|
|
71
|
+
* Copyright 2017 Google LLC
|
|
72
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
73
|
+
*/function r(r){return n({...r,state:!0,attribute:!1})}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @license
|
|
77
|
+
* Copyright 2020 Google LLC
|
|
78
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
79
|
+
*/const st=o=>null===o||"object"!=typeof o&&"function"!=typeof o,rt=o=>void 0===o.strings;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @license
|
|
83
|
+
* Copyright 2017 Google LLC
|
|
84
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
85
|
+
*/
|
|
86
|
+
const t={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},e=t=>(...e)=>({_$litDirective$:t,values:e});class i{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this.t=t,this._$AM=e,this.i=i;}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @license
|
|
90
|
+
* Copyright 2017 Google LLC
|
|
91
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
92
|
+
*/const mt=(i,t)=>{const e=i._$AN;if(void 0===e)return !1;for(const i of e)i._$AO?.(t,!1),mt(i,t);return !0},_t=i=>{let t,e;do{if(void 0===(t=i._$AM))break;e=t._$AN,e.delete(i),i=t;}while(0===e?.size)},wt=i=>{for(let t;t=i._$AM;i=t){let e=t._$AN;if(void 0===e)t._$AN=e=new Set;else if(e.has(i))break;e.add(i),gt(t);}};function bt(i){void 0!==this._$AN?(_t(this),this._$AM=i,wt(this)):this._$AM=i;}function yt(i,t=!1,e=0){const s=this._$AH,o=this._$AN;if(void 0!==o&&0!==o.size)if(t)if(Array.isArray(s))for(let i=e;i<s.length;i++)mt(s[i],!1),_t(s[i]);else null!=s&&(mt(s,!1),_t(s));else mt(this,i);}const gt=i=>{i.type==t.CHILD&&(i._$AP??=yt,i._$AQ??=bt);};class $t extends i{constructor(){super(...arguments),this._$AN=void 0;}_$AT(i,t,e){super._$AT(i,t,e),wt(this),this.isConnected=i._$AU;}_$AO(i,t=!0){i!==this.isConnected&&(this.isConnected=i,i?this.reconnected?.():this.disconnected?.()),t&&(mt(this,i),_t(this));}setValue(i){if(rt(this.t))this.t._$AI(i,this);else {const t=[...this.t._$AH];t[this.i]=i,this.t._$AI(t,this,0);}}disconnected(){}reconnected(){}}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @license
|
|
96
|
+
* Copyright 2020 Google LLC
|
|
97
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
98
|
+
*/const ii=()=>new Zt;class Zt{}const qt=new WeakMap,Kt=e(class extends $t{render(t){return D}update(t,[i]){const s=i!==this.Y;return s&&void 0!==this.Y&&this.rt(void 0),(s||this.lt!==this.ct)&&(this.Y=i,this.ht=t.options?.host,this.rt(this.ct=t.element)),D}rt(t){if(this.isConnected||(t=void 0),"function"==typeof this.Y){const i=this.ht??globalThis;let s=qt.get(i);void 0===s&&(s=new WeakMap,qt.set(i,s)),void 0!==s.get(this.Y)&&this.Y.call(this.ht,void 0),s.set(this.Y,t),void 0!==t&&this.Y.call(this.ht,t);}else this.Y.value=t;}get lt(){return "function"==typeof this.Y?qt.get(this.ht??globalThis)?.get(this.Y):this.Y?.value}disconnected(){this.lt===this.ct&&this.rt(void 0);}reconnected(){this.rt(this.ct);}});
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 在原生的 HTML 中,布尔属性只要添加了属性名,不论属性值设置成什么,属性值都是 true
|
|
102
|
+
* 但这里设置了 attr="false" 时,要把属性设置为 false
|
|
103
|
+
*
|
|
104
|
+
* 原因是:
|
|
105
|
+
* 在 vue3 中,通过 :attr="value" 设置属性时,vue 会优先从 DOM 属性中寻找是否存在 attr 属性名,
|
|
106
|
+
* 若存在,则设置对应的 DOM 属性,否则设置对应的 attribute 属性
|
|
107
|
+
* 但在 vue 的服务端渲染(ssr)时,不存在 DOM 对象,所以会把 attribute 属性设置成 attr="true" 或 attr="false"
|
|
108
|
+
* 所以在 attribute 属性 attr="false" 时,需要把属性值转换为布尔值 false
|
|
109
|
+
*
|
|
110
|
+
* 这段代码不能封装成函数,否则生成 custom-elements.json 会识别不了
|
|
111
|
+
* 这段注释仅在这里写一次,其他地方不再重复
|
|
112
|
+
*
|
|
113
|
+
* @see https://v3-migration.vuejs.org/zh/breaking-changes/attribute-coercion.html
|
|
114
|
+
*/
|
|
115
|
+
const booleanConverter = (value) => {
|
|
116
|
+
return value !== null && value !== 'false';
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const nothingTemplate = ke `${D}`;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @license
|
|
123
|
+
* Copyright 2018 Google LLC
|
|
124
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
125
|
+
*/const ee="important",ie=" !"+ee,se=e(class extends i{constructor(e){if(super(e),e.type!==t.ATTRIBUTE||"style"!==e.name||e.strings?.length>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(t){return Object.keys(t).reduce(((e,r)=>{const s=t[r];return null==s?e:e+`${r=r.includes("-")?r:r.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${s};`}),"")}update(t,[e]){const{style:r}=t.element;if(void 0===this.ft)return this.ft=new Set(Object.keys(e)),this.render(e);for(const t of this.ft)null==e[t]&&(this.ft.delete(t),t.includes("-")?r.removeProperty(t):r[t]=null);for(const t in e){const s=e[t];if(null!=s){this.ft.add(t);const e="string"==typeof s&&s.endsWith(ie);t.includes("-")||e?r.setProperty(t,e?s.slice(0,-11):s,e?ee:""):r[t]=s;}}return R}});
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @license
|
|
129
|
+
* Copyright 2017 Google LLC
|
|
130
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
131
|
+
*/class le extends i{constructor(i){if(super(i),this.it=D,i.type!==t.CHILD)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(t){if(t===D||null==t)return this._t=void 0,this.it=t;if(t===R)return t;if("string"!=typeof t)throw Error(this.constructor.directiveName+"() called with a non-string value");if(t===this.it)return this._t;this.it=t;const i=[t];return i.raw=i,this._t={_$litType$:this.constructor.resultType,strings:i,values:[]}}}le.directiveName="unsafeHTML",le.resultType=1;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @license
|
|
135
|
+
* Copyright 2017 Google LLC
|
|
136
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
137
|
+
*/class pe extends le{}pe.directiveName="unsafeSVG",pe.resultType=2;const fe=e(pe);
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @license
|
|
141
|
+
* Copyright 2021 Google LLC
|
|
142
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
143
|
+
*/
|
|
144
|
+
class Tt{constructor(t){this.Y=t;}disconnect(){this.Y=void 0;}reconnect(t){this.Y=t;}deref(){return this.Y}}class Et{constructor(){this.Z=void 0,this.q=void 0;}get(){return this.Z}pause(){this.Z??=new Promise((t=>this.q=t));}resume(){this.q?.(),this.Z=this.q=void 0;}}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @license
|
|
148
|
+
* Copyright 2017 Google LLC
|
|
149
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
150
|
+
*/const me=t=>!st(t)&&"function"==typeof t.then,_e=1073741823;class we extends $t{constructor(){super(...arguments),this.wt=_e,this.bt=[],this.K=new Tt(this),this.X=new Et;}render(...t){return t.find((t=>!me(t)))??R}update(t,s){const i=this.bt;let e=i.length;this.bt=s;const r=this.K,o=this.X;this.isConnected||this.disconnected();for(let t=0;t<s.length&&!(t>this.wt);t++){const n=s[t];if(!me(n))return this.wt=t,n;t<e&&n===i[t]||(this.wt=_e,e=0,Promise.resolve(n).then((async t=>{for(;o.get();)await o.get();const s=r.deref();if(void 0!==s){const i=s.bt.indexOf(n);i>-1&&i<s.wt&&(s.wt=i,s.setValue(t));}})));}return R}disconnected(){this.K.disconnect(),this.X.pause();}reconnected(){this.K.reconnect(this),this.X.resume();}}const be=e(we);
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* SSR Window 4.0.2
|
|
154
|
+
* Better handling for window object in SSR environment
|
|
155
|
+
* https://github.com/nolimits4web/ssr-window
|
|
156
|
+
*
|
|
157
|
+
* Copyright 2021, Vladimir Kharlampidi
|
|
158
|
+
*
|
|
159
|
+
* Licensed under MIT
|
|
160
|
+
*
|
|
161
|
+
* Released on: December 13, 2021
|
|
162
|
+
*/
|
|
163
|
+
/* eslint-disable no-param-reassign */
|
|
164
|
+
function isObject(obj) {
|
|
165
|
+
return (obj !== null &&
|
|
166
|
+
typeof obj === 'object' &&
|
|
167
|
+
'constructor' in obj &&
|
|
168
|
+
obj.constructor === Object);
|
|
169
|
+
}
|
|
170
|
+
function extend$1(target = {}, src = {}) {
|
|
171
|
+
Object.keys(src).forEach((key) => {
|
|
172
|
+
if (typeof target[key] === 'undefined')
|
|
173
|
+
target[key] = src[key];
|
|
174
|
+
else if (isObject(src[key]) &&
|
|
175
|
+
isObject(target[key]) &&
|
|
176
|
+
Object.keys(src[key]).length > 0) {
|
|
177
|
+
extend$1(target[key], src[key]);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const ssrDocument = {
|
|
183
|
+
body: {},
|
|
184
|
+
addEventListener() { },
|
|
185
|
+
removeEventListener() { },
|
|
186
|
+
activeElement: {
|
|
187
|
+
blur() { },
|
|
188
|
+
nodeName: '',
|
|
189
|
+
},
|
|
190
|
+
querySelector() {
|
|
191
|
+
return null;
|
|
192
|
+
},
|
|
193
|
+
querySelectorAll() {
|
|
194
|
+
return [];
|
|
195
|
+
},
|
|
196
|
+
getElementById() {
|
|
197
|
+
return null;
|
|
198
|
+
},
|
|
199
|
+
createEvent() {
|
|
200
|
+
return {
|
|
201
|
+
initEvent() { },
|
|
202
|
+
};
|
|
203
|
+
},
|
|
204
|
+
createElement() {
|
|
205
|
+
return {
|
|
206
|
+
children: [],
|
|
207
|
+
childNodes: [],
|
|
208
|
+
style: {},
|
|
209
|
+
setAttribute() { },
|
|
210
|
+
getElementsByTagName() {
|
|
211
|
+
return [];
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
},
|
|
215
|
+
createElementNS() {
|
|
216
|
+
return {};
|
|
217
|
+
},
|
|
218
|
+
importNode() {
|
|
219
|
+
return null;
|
|
220
|
+
},
|
|
221
|
+
location: {
|
|
222
|
+
hash: '',
|
|
223
|
+
host: '',
|
|
224
|
+
hostname: '',
|
|
225
|
+
href: '',
|
|
226
|
+
origin: '',
|
|
227
|
+
pathname: '',
|
|
228
|
+
protocol: '',
|
|
229
|
+
search: '',
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
function getDocument() {
|
|
233
|
+
const doc = typeof document !== 'undefined' ? document : {};
|
|
234
|
+
extend$1(doc, ssrDocument);
|
|
235
|
+
return doc;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const ssrWindow = {
|
|
239
|
+
document: ssrDocument,
|
|
240
|
+
navigator: {
|
|
241
|
+
userAgent: '',
|
|
242
|
+
},
|
|
243
|
+
location: {
|
|
244
|
+
hash: '',
|
|
245
|
+
host: '',
|
|
246
|
+
hostname: '',
|
|
247
|
+
href: '',
|
|
248
|
+
origin: '',
|
|
249
|
+
pathname: '',
|
|
250
|
+
protocol: '',
|
|
251
|
+
search: '',
|
|
252
|
+
},
|
|
253
|
+
history: {
|
|
254
|
+
replaceState() { },
|
|
255
|
+
pushState() { },
|
|
256
|
+
go() { },
|
|
257
|
+
back() { },
|
|
258
|
+
},
|
|
259
|
+
CustomEvent: function CustomEvent() {
|
|
260
|
+
return this;
|
|
261
|
+
},
|
|
262
|
+
addEventListener() { },
|
|
263
|
+
removeEventListener() { },
|
|
264
|
+
getComputedStyle() {
|
|
265
|
+
return {
|
|
266
|
+
getPropertyValue() {
|
|
267
|
+
return '';
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
},
|
|
271
|
+
Image() { },
|
|
272
|
+
Date() { },
|
|
273
|
+
screen: {},
|
|
274
|
+
setTimeout() { },
|
|
275
|
+
clearTimeout() { },
|
|
276
|
+
matchMedia() {
|
|
277
|
+
return {};
|
|
278
|
+
},
|
|
279
|
+
requestAnimationFrame(callback) {
|
|
280
|
+
if (typeof setTimeout === 'undefined') {
|
|
281
|
+
callback();
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
return setTimeout(callback, 0);
|
|
285
|
+
},
|
|
286
|
+
cancelAnimationFrame(id) {
|
|
287
|
+
if (typeof setTimeout === 'undefined') {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
clearTimeout(id);
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
function getWindow() {
|
|
294
|
+
const win = typeof window !== 'undefined' ? window : {};
|
|
295
|
+
extend$1(win, ssrWindow);
|
|
296
|
+
return win;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* 获取指定元素的标签名(小写),不存在元素的返回空字符串
|
|
301
|
+
* @param element
|
|
302
|
+
*/
|
|
303
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
304
|
+
const isFunction = (target) => {
|
|
305
|
+
return typeof target === 'function';
|
|
306
|
+
};
|
|
307
|
+
const isString = (target) => {
|
|
308
|
+
return typeof target === 'string';
|
|
309
|
+
};
|
|
310
|
+
const isNumber = (target) => {
|
|
311
|
+
return typeof target === 'number';
|
|
312
|
+
};
|
|
313
|
+
const isBoolean = (target) => {
|
|
314
|
+
return typeof target === 'boolean';
|
|
315
|
+
};
|
|
316
|
+
const isUndefined = (target) => {
|
|
317
|
+
return typeof target === 'undefined';
|
|
318
|
+
};
|
|
319
|
+
const isNull = (target) => {
|
|
320
|
+
return target === null;
|
|
321
|
+
};
|
|
322
|
+
const isWindow = (target) => {
|
|
323
|
+
return typeof Window !== 'undefined' && target instanceof Window;
|
|
324
|
+
};
|
|
325
|
+
const isDocument = (target) => {
|
|
326
|
+
return typeof Document !== 'undefined' && target instanceof Document;
|
|
327
|
+
};
|
|
328
|
+
const isElement = (target) => {
|
|
329
|
+
return typeof Element !== 'undefined' && target instanceof Element;
|
|
330
|
+
};
|
|
331
|
+
const isNode = (target) => {
|
|
332
|
+
return typeof Node !== 'undefined' && target instanceof Node;
|
|
333
|
+
};
|
|
334
|
+
const isArrayLike = (target) => {
|
|
335
|
+
return (!isFunction(target) &&
|
|
336
|
+
!isWindow(target) &&
|
|
337
|
+
isNumber(target.length));
|
|
338
|
+
};
|
|
339
|
+
const isObjectLike = (target) => {
|
|
340
|
+
return typeof target === 'object' && target !== null;
|
|
341
|
+
};
|
|
342
|
+
const toElement = (target) => {
|
|
343
|
+
return isDocument(target) ? target.documentElement : target;
|
|
344
|
+
};
|
|
345
|
+
/**
|
|
346
|
+
* 把用 - 分隔的字符串转为驼峰(如 box-sizing 转换为 boxSizing)
|
|
347
|
+
* @param string
|
|
348
|
+
*/
|
|
349
|
+
const toCamelCase = (string) => {
|
|
350
|
+
return string.replace(/-([a-z])/g, (_, letter) => {
|
|
351
|
+
return letter.toUpperCase();
|
|
352
|
+
});
|
|
353
|
+
};
|
|
354
|
+
/**
|
|
355
|
+
* 把驼峰法转为用 - 分隔的字符串(如 boxSizing 转换为 box-sizing)
|
|
356
|
+
* @param string
|
|
357
|
+
*/
|
|
358
|
+
const toKebabCase = (string) => {
|
|
359
|
+
if (!string) {
|
|
360
|
+
return string;
|
|
361
|
+
}
|
|
362
|
+
return string
|
|
363
|
+
.replace(/^./, string[0].toLowerCase()) // 首字母转小写
|
|
364
|
+
.replace(/[A-Z]/g, (replacer) => {
|
|
365
|
+
return '-' + replacer.toLowerCase();
|
|
366
|
+
});
|
|
367
|
+
};
|
|
368
|
+
/**
|
|
369
|
+
* 始终返回 false 的函数
|
|
370
|
+
*/
|
|
371
|
+
const returnFalse = () => {
|
|
372
|
+
return false;
|
|
373
|
+
};
|
|
374
|
+
/**
|
|
375
|
+
* 遍历数组
|
|
376
|
+
* @param target
|
|
377
|
+
* @param callback
|
|
378
|
+
*/
|
|
379
|
+
const eachArray = (target, callback) => {
|
|
380
|
+
for (let i = 0; i < target.length; i += 1) {
|
|
381
|
+
if (callback.call(target[i], target[i], i) === false) {
|
|
382
|
+
return target;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return target;
|
|
386
|
+
};
|
|
387
|
+
/**
|
|
388
|
+
* 遍历对象
|
|
389
|
+
* @param target
|
|
390
|
+
* @param callback
|
|
391
|
+
*/
|
|
392
|
+
const eachObject = (target, callback) => {
|
|
393
|
+
const keys = Object.keys(target);
|
|
394
|
+
for (let i = 0; i < keys.length; i += 1) {
|
|
395
|
+
const key = keys[i];
|
|
396
|
+
if (callback.call(target[key], key, target[key]) === false) {
|
|
397
|
+
return target;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return target;
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* 为了使用模块扩充,这里不能使用默认导出
|
|
405
|
+
*/
|
|
406
|
+
class JQ {
|
|
407
|
+
constructor(arr) {
|
|
408
|
+
this.length = 0;
|
|
409
|
+
if (!arr) {
|
|
410
|
+
return this;
|
|
411
|
+
}
|
|
412
|
+
eachArray(arr, (item, i) => {
|
|
413
|
+
this[i] = item;
|
|
414
|
+
});
|
|
415
|
+
this.length = arr.length;
|
|
416
|
+
return this;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* DOM 是否已加载完成
|
|
422
|
+
*
|
|
423
|
+
* 在 Web Components 中操作组件外部的 DOM、或组件中的 slot 的 DOM 时,必须先判断 DOM 是否已加载完成。
|
|
424
|
+
*/
|
|
425
|
+
const isDomReady = (document = getDocument()) => {
|
|
426
|
+
return /complete|interactive/.test(document.readyState);
|
|
427
|
+
};
|
|
428
|
+
const createElement = (tagName) => {
|
|
429
|
+
const document = getDocument();
|
|
430
|
+
return document.createElement(tagName);
|
|
431
|
+
};
|
|
432
|
+
const appendChild = (element, child) => {
|
|
433
|
+
return element.appendChild(child);
|
|
434
|
+
};
|
|
435
|
+
const removeChild = (element) => {
|
|
436
|
+
return element.parentNode ? element.parentNode.removeChild(element) : element;
|
|
437
|
+
};
|
|
438
|
+
/**
|
|
439
|
+
* 获取子节点组成的数组
|
|
440
|
+
* @param target
|
|
441
|
+
* @param parent
|
|
442
|
+
*/
|
|
443
|
+
const getChildNodesArray = (target, parent) => {
|
|
444
|
+
const tempParent = createElement(parent);
|
|
445
|
+
tempParent.innerHTML = target;
|
|
446
|
+
return [].slice.call(tempParent.childNodes);
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
const get$ = () => {
|
|
450
|
+
const $ = function (selector) {
|
|
451
|
+
if (!selector) {
|
|
452
|
+
return new JQ();
|
|
453
|
+
}
|
|
454
|
+
// JQ
|
|
455
|
+
if (selector instanceof JQ) {
|
|
456
|
+
return selector;
|
|
457
|
+
}
|
|
458
|
+
// function
|
|
459
|
+
if (isFunction(selector)) {
|
|
460
|
+
const document = getDocument();
|
|
461
|
+
if (isDomReady(document)) {
|
|
462
|
+
selector.call(document, $);
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
document.addEventListener('DOMContentLoaded', () => selector.call(document, $), { once: true });
|
|
466
|
+
}
|
|
467
|
+
return new JQ([document]);
|
|
468
|
+
}
|
|
469
|
+
// String
|
|
470
|
+
if (isString(selector)) {
|
|
471
|
+
const html = selector.trim();
|
|
472
|
+
// 根据 HTML 字符串创建 JQ 对象
|
|
473
|
+
if (html.startsWith('<') && html.endsWith('>')) {
|
|
474
|
+
let toCreate = 'div';
|
|
475
|
+
const tags = {
|
|
476
|
+
li: 'ul',
|
|
477
|
+
tr: 'tbody',
|
|
478
|
+
td: 'tr',
|
|
479
|
+
th: 'tr',
|
|
480
|
+
tbody: 'table',
|
|
481
|
+
option: 'select',
|
|
482
|
+
};
|
|
483
|
+
eachObject(tags, (childTag, parentTag) => {
|
|
484
|
+
if (html.startsWith(`<${childTag}`)) {
|
|
485
|
+
toCreate = parentTag;
|
|
486
|
+
return false;
|
|
487
|
+
}
|
|
488
|
+
return;
|
|
489
|
+
});
|
|
490
|
+
return new JQ(getChildNodesArray(html, toCreate));
|
|
491
|
+
}
|
|
492
|
+
const document = getDocument();
|
|
493
|
+
// 根据 CSS 选择器创建 JQ 对象
|
|
494
|
+
return new JQ(document.querySelectorAll(selector));
|
|
495
|
+
}
|
|
496
|
+
if (isArrayLike(selector) && !isNode(selector)) {
|
|
497
|
+
return new JQ(selector);
|
|
498
|
+
}
|
|
499
|
+
return new JQ([selector]);
|
|
500
|
+
};
|
|
501
|
+
$.fn = JQ.prototype;
|
|
502
|
+
return $;
|
|
503
|
+
};
|
|
504
|
+
const $ = get$();
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* 检查 container 元素内是否包含 contains 元素
|
|
508
|
+
* @param container 父元素
|
|
509
|
+
* @param contains 子元素
|
|
510
|
+
* @example
|
|
511
|
+
```js
|
|
512
|
+
contains( document, document.body ); // true
|
|
513
|
+
contains( document.getElementById('test'), document ); // false
|
|
514
|
+
contains( $('.container').get(0), $('.contains').get(0) ); // false
|
|
515
|
+
```
|
|
516
|
+
*/
|
|
517
|
+
const contains = (container, contains) => {
|
|
518
|
+
return container !== contains && toElement(container).contains(contains);
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* 把第二个数组的元素追加到第一个数组中,并返回合并后的数组
|
|
523
|
+
* @param first 第一个数组
|
|
524
|
+
* @param second 该数组的元素将被追加到第一个数组中
|
|
525
|
+
* @example
|
|
526
|
+
```js
|
|
527
|
+
merge( [ 0, 1, 2 ], [ 2, 3, 4 ] )
|
|
528
|
+
// [ 0, 1, 2, 2, 3, 4 ]
|
|
529
|
+
```
|
|
530
|
+
*/
|
|
531
|
+
const merge = (first, second) => {
|
|
532
|
+
eachArray(second, (value) => {
|
|
533
|
+
first.push(value);
|
|
534
|
+
});
|
|
535
|
+
return first;
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
// eslint-disable-next-line
|
|
539
|
+
$.fn.each = function (callback) {
|
|
540
|
+
return eachArray(this, (value, index) => {
|
|
541
|
+
return callback.call(value, index, value);
|
|
542
|
+
});
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
// eslint-disable-next-line
|
|
546
|
+
$.fn.get = function (index) {
|
|
547
|
+
return index === undefined
|
|
548
|
+
? [].slice.call(this)
|
|
549
|
+
: this[index >= 0 ? index : index + this.length];
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
$.fn.find = function (selector) {
|
|
553
|
+
const foundElements = [];
|
|
554
|
+
this.each((_, element) => {
|
|
555
|
+
merge(foundElements, $(element.querySelectorAll(selector)).get());
|
|
556
|
+
});
|
|
557
|
+
return new JQ(foundElements);
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
// 直接使用 CustomEvent 在 ssr 环境下会报错
|
|
561
|
+
const CustomEvent$1 = getWindow().CustomEvent;
|
|
562
|
+
/**
|
|
563
|
+
* 封装 CustomEvent,使之支持 data:事件监听参数,namespace:命名空间
|
|
564
|
+
*/
|
|
565
|
+
class MduiCustomEvent extends CustomEvent$1 {
|
|
566
|
+
constructor(type, options) {
|
|
567
|
+
super(type, options);
|
|
568
|
+
this.data = options.data;
|
|
569
|
+
this.namespace = options.namespace;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
const elementIdMap = new WeakMap();
|
|
573
|
+
let elementId = 1;
|
|
574
|
+
/**
|
|
575
|
+
* 为元素赋予一个唯一的ID
|
|
576
|
+
*/
|
|
577
|
+
const getElementId = (element) => {
|
|
578
|
+
if (!elementIdMap.has(element)) {
|
|
579
|
+
elementIdMap.set(element, ++elementId);
|
|
580
|
+
}
|
|
581
|
+
return elementIdMap.get(element);
|
|
582
|
+
};
|
|
583
|
+
// 存储唯一ID及事件处理
|
|
584
|
+
const handlersMap = new Map();
|
|
585
|
+
/**
|
|
586
|
+
* 获取元素上的事件处理器数组
|
|
587
|
+
* @param element
|
|
588
|
+
*/
|
|
589
|
+
const getHandlers = (element) => {
|
|
590
|
+
const id = getElementId(element);
|
|
591
|
+
return handlersMap.get(id) || handlersMap.set(id, []).get(id);
|
|
592
|
+
};
|
|
593
|
+
/**
|
|
594
|
+
* 解析事件名中的命名空间
|
|
595
|
+
*/
|
|
596
|
+
const parse = (type) => {
|
|
597
|
+
const parts = type.split('.');
|
|
598
|
+
return {
|
|
599
|
+
type: parts[0],
|
|
600
|
+
namespace: parts.slice(1).sort().join(' '),
|
|
601
|
+
};
|
|
602
|
+
};
|
|
603
|
+
/**
|
|
604
|
+
* 命名空间匹配规则
|
|
605
|
+
*/
|
|
606
|
+
const matcherFor = (namespace) => {
|
|
607
|
+
return new RegExp('(?:^| )' + namespace.replace(' ', ' .* ?') + '(?: |$)');
|
|
608
|
+
};
|
|
609
|
+
/**
|
|
610
|
+
* 获取匹配的事件
|
|
611
|
+
* @param element
|
|
612
|
+
* @param type
|
|
613
|
+
* @param func
|
|
614
|
+
* @param selector
|
|
615
|
+
*/
|
|
616
|
+
const getMatchedHandlers = (element, type, func, selector) => {
|
|
617
|
+
const event = parse(type);
|
|
618
|
+
return getHandlers(element).filter((handler) => {
|
|
619
|
+
return (handler &&
|
|
620
|
+
(!event.type || handler.type === event.type) &&
|
|
621
|
+
(!event.namespace ||
|
|
622
|
+
matcherFor(event.namespace).test(handler.namespace)) &&
|
|
623
|
+
(!func || getElementId(handler.func) === getElementId(func)) &&
|
|
624
|
+
(!selector || handler.selector === selector));
|
|
625
|
+
});
|
|
626
|
+
};
|
|
627
|
+
/**
|
|
628
|
+
* 添加事件监听
|
|
629
|
+
* @param element
|
|
630
|
+
* @param types
|
|
631
|
+
* @param func
|
|
632
|
+
* @param data
|
|
633
|
+
* @param selector
|
|
634
|
+
*/
|
|
635
|
+
const add = (element, types, func, data, selector) => {
|
|
636
|
+
// 传入 data.useCapture 来设置 useCapture: true
|
|
637
|
+
let useCapture = false;
|
|
638
|
+
if (isObjectLike(data) && data.useCapture) {
|
|
639
|
+
useCapture = true;
|
|
640
|
+
}
|
|
641
|
+
types.split(' ').forEach((type) => {
|
|
642
|
+
if (!type) {
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
const event = parse(type);
|
|
646
|
+
const callFn = (e, elem) => {
|
|
647
|
+
const result = func.apply(elem,
|
|
648
|
+
// @ts-ignore
|
|
649
|
+
e.detail === null ? [e] : [e].concat(e.detail));
|
|
650
|
+
if (result === false) {
|
|
651
|
+
e.preventDefault();
|
|
652
|
+
e.stopPropagation();
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
const proxyFn = (e) => {
|
|
656
|
+
if (e.namespace && !matcherFor(e.namespace).test(event.namespace)) {
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
e.data = data;
|
|
660
|
+
if (selector) {
|
|
661
|
+
// 事件代理
|
|
662
|
+
$(element)
|
|
663
|
+
.find(selector)
|
|
664
|
+
.get()
|
|
665
|
+
.reverse()
|
|
666
|
+
.forEach((elem) => {
|
|
667
|
+
if (elem === e.target || contains(elem, e.target)) {
|
|
668
|
+
callFn(e, elem);
|
|
669
|
+
}
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
else {
|
|
673
|
+
// 不使用事件代理
|
|
674
|
+
callFn(e, element);
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
const handler = {
|
|
678
|
+
type: event.type,
|
|
679
|
+
namespace: event.namespace,
|
|
680
|
+
func,
|
|
681
|
+
selector,
|
|
682
|
+
id: getHandlers(element).length,
|
|
683
|
+
proxy: proxyFn,
|
|
684
|
+
};
|
|
685
|
+
getHandlers(element).push(handler);
|
|
686
|
+
// @ts-ignore
|
|
687
|
+
element.addEventListener(handler.type, proxyFn, useCapture);
|
|
688
|
+
});
|
|
689
|
+
};
|
|
690
|
+
/**
|
|
691
|
+
* 移除事件监听
|
|
692
|
+
* @param element
|
|
693
|
+
* @param types
|
|
694
|
+
* @param func
|
|
695
|
+
* @param selector
|
|
696
|
+
*/
|
|
697
|
+
const remove = (element, types, func, selector) => {
|
|
698
|
+
const handlersInElement = getHandlers(element);
|
|
699
|
+
const removeEvent = (handler) => {
|
|
700
|
+
delete handlersInElement[handler.id];
|
|
701
|
+
// @ts-ignore
|
|
702
|
+
element.removeEventListener(handler.type, handler.proxy, false);
|
|
703
|
+
};
|
|
704
|
+
if (!types) {
|
|
705
|
+
handlersInElement.forEach((handler) => {
|
|
706
|
+
removeEvent(handler);
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
types.split(' ').forEach((type) => {
|
|
711
|
+
if (type) {
|
|
712
|
+
getMatchedHandlers(element, type, func, selector).forEach((handler) => {
|
|
713
|
+
removeEvent(handler);
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
$.fn.trigger = function (name,
|
|
721
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
722
|
+
detail = null, options) {
|
|
723
|
+
const { type, namespace } = parse(name);
|
|
724
|
+
const event = new MduiCustomEvent(type, {
|
|
725
|
+
detail,
|
|
726
|
+
data: null,
|
|
727
|
+
namespace,
|
|
728
|
+
bubbles: true,
|
|
729
|
+
cancelable: false,
|
|
730
|
+
composed: true,
|
|
731
|
+
...options,
|
|
732
|
+
});
|
|
733
|
+
return this.each((_, element) => {
|
|
734
|
+
element.dispatchEvent(event);
|
|
735
|
+
});
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
function extend(target, ...objectN) {
|
|
739
|
+
eachArray(objectN, (object) => {
|
|
740
|
+
eachObject(object, (prop, value) => {
|
|
741
|
+
if (!isUndefined(value)) {
|
|
742
|
+
target[prop] = value;
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
});
|
|
746
|
+
return target;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// 全局事件名
|
|
750
|
+
const ajaxStart = 'ajaxStart';
|
|
751
|
+
const ajaxSuccess = 'ajaxSuccess';
|
|
752
|
+
const ajaxError = 'ajaxError';
|
|
753
|
+
const ajaxComplete = 'ajaxComplete';
|
|
754
|
+
// 全局配置参数
|
|
755
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
756
|
+
const globalOptions = {};
|
|
757
|
+
/**
|
|
758
|
+
* 判断此请求方法是否通过查询字符串提交参数
|
|
759
|
+
* @param method 请求方法,大写
|
|
760
|
+
*/
|
|
761
|
+
const isQueryStringData = (method) => {
|
|
762
|
+
return ['GET', 'HEAD'].includes(method);
|
|
763
|
+
};
|
|
764
|
+
/**
|
|
765
|
+
* 添加参数到 URL 上,且 URL 中不存在 ? 时,自动把第一个 & 替换为 ?
|
|
766
|
+
* @param url
|
|
767
|
+
* @param query
|
|
768
|
+
*/
|
|
769
|
+
const appendQuery = (url, query) => {
|
|
770
|
+
return `${url}&${query}`.replace(/[&?]{1,2}/, '?');
|
|
771
|
+
};
|
|
772
|
+
/**
|
|
773
|
+
* url 是否跨域
|
|
774
|
+
* @param url
|
|
775
|
+
*/
|
|
776
|
+
const isCrossDomain = (url) => {
|
|
777
|
+
const window = getWindow();
|
|
778
|
+
return (/^([\w-]+:)?\/\/([^/]+)/.test(url) && RegExp.$2 !== window.location.host);
|
|
779
|
+
};
|
|
780
|
+
/**
|
|
781
|
+
* HTTP 状态码是否表示请求成功
|
|
782
|
+
* @param status
|
|
783
|
+
*/
|
|
784
|
+
const isHttpStatusSuccess = (status) => {
|
|
785
|
+
return (status >= 200 && status < 300) || [0, 304].includes(status);
|
|
786
|
+
};
|
|
787
|
+
/**
|
|
788
|
+
* 合并请求参数,参数优先级:options > globalOptions > defaults
|
|
789
|
+
* @param options
|
|
790
|
+
*/
|
|
791
|
+
const mergeOptions = (options) => {
|
|
792
|
+
// 默认参数
|
|
793
|
+
const defaults = {
|
|
794
|
+
url: '',
|
|
795
|
+
method: 'GET',
|
|
796
|
+
data: '',
|
|
797
|
+
processData: true,
|
|
798
|
+
async: true,
|
|
799
|
+
cache: true,
|
|
800
|
+
username: '',
|
|
801
|
+
password: '',
|
|
802
|
+
headers: {},
|
|
803
|
+
xhrFields: {},
|
|
804
|
+
statusCode: {},
|
|
805
|
+
dataType: '',
|
|
806
|
+
contentType: 'application/x-www-form-urlencoded',
|
|
807
|
+
timeout: 0,
|
|
808
|
+
global: true,
|
|
809
|
+
};
|
|
810
|
+
// globalOptions 中的回调函数不合并
|
|
811
|
+
eachObject(globalOptions, (key, value) => {
|
|
812
|
+
const callbacks = [
|
|
813
|
+
'beforeSend',
|
|
814
|
+
'success',
|
|
815
|
+
'error',
|
|
816
|
+
'complete',
|
|
817
|
+
'statusCode',
|
|
818
|
+
];
|
|
819
|
+
if (!callbacks.includes(key) && !isUndefined(value)) {
|
|
820
|
+
defaults[key] = value;
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
return extend({}, defaults, options);
|
|
824
|
+
};
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* 将数组或对象序列化,序列化后的字符串可作为 URL 查询字符串使用
|
|
828
|
+
*
|
|
829
|
+
* 若传入数组,则格式必须和 serializeArray 方法的返回值一样
|
|
830
|
+
* @param obj 对象或数组
|
|
831
|
+
* @example
|
|
832
|
+
```js
|
|
833
|
+
param({ width: 1680, height: 1050 });
|
|
834
|
+
// width=1680&height=1050
|
|
835
|
+
```
|
|
836
|
+
* @example
|
|
837
|
+
```js
|
|
838
|
+
param({ foo: { one: 1, two: 2 }})
|
|
839
|
+
// foo[one]=1&foo[two]=2
|
|
840
|
+
```
|
|
841
|
+
* @example
|
|
842
|
+
```js
|
|
843
|
+
param({ids: [1, 2, 3]})
|
|
844
|
+
// ids[]=1&ids[]=2&ids[]=3
|
|
845
|
+
```
|
|
846
|
+
* @example
|
|
847
|
+
```js
|
|
848
|
+
param([
|
|
849
|
+
{"name":"name","value":"mdui"},
|
|
850
|
+
{"name":"password","value":"123456"}
|
|
851
|
+
])
|
|
852
|
+
// name=mdui&password=123456
|
|
853
|
+
```
|
|
854
|
+
*/
|
|
855
|
+
const param = (obj) => {
|
|
856
|
+
if (!isObjectLike(obj) && !Array.isArray(obj)) {
|
|
857
|
+
return '';
|
|
858
|
+
}
|
|
859
|
+
const args = [];
|
|
860
|
+
const destructure = (key, value) => {
|
|
861
|
+
let keyTmp;
|
|
862
|
+
if (isObjectLike(value)) {
|
|
863
|
+
eachObject(value, (i, v) => {
|
|
864
|
+
keyTmp = Array.isArray(value) && !isObjectLike(v) ? '' : i;
|
|
865
|
+
destructure(`${key}[${keyTmp}]`, v);
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
else {
|
|
869
|
+
keyTmp =
|
|
870
|
+
value == null || value === '' ? '=' : `=${encodeURIComponent(value)}`;
|
|
871
|
+
args.push(encodeURIComponent(key) + keyTmp);
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
if (Array.isArray(obj)) {
|
|
875
|
+
eachArray(obj, ({ name, value }) => {
|
|
876
|
+
return destructure(name, value);
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
else {
|
|
880
|
+
eachObject(obj, destructure);
|
|
881
|
+
}
|
|
882
|
+
return args.join('&');
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* 发送 ajax 请求
|
|
887
|
+
* @param options
|
|
888
|
+
* @example
|
|
889
|
+
```js
|
|
890
|
+
ajax({
|
|
891
|
+
method: "POST",
|
|
892
|
+
url: "some.php",
|
|
893
|
+
data: { name: "John", location: "Boston" }
|
|
894
|
+
}).then(function( msg ) {
|
|
895
|
+
alert( "Data Saved: " + msg );
|
|
896
|
+
});
|
|
897
|
+
```
|
|
898
|
+
*/
|
|
899
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
900
|
+
const ajax = (options) => {
|
|
901
|
+
const document = getDocument();
|
|
902
|
+
const window = getWindow();
|
|
903
|
+
// 是否已取消请求
|
|
904
|
+
let isCanceled = false;
|
|
905
|
+
// ajaxStart、ajaxError、ajaxComplete 事件参数
|
|
906
|
+
// @ts-ignore
|
|
907
|
+
const eventParams = {};
|
|
908
|
+
// ajaxSuccess 事件参数
|
|
909
|
+
// @ts-ignore
|
|
910
|
+
const successEventParams = {};
|
|
911
|
+
// 参数合并
|
|
912
|
+
const mergedOptions = mergeOptions(options);
|
|
913
|
+
const method = mergedOptions.method.toUpperCase();
|
|
914
|
+
let { data, url } = mergedOptions;
|
|
915
|
+
url = url || window.location.toString();
|
|
916
|
+
const { processData, async, cache, username, password, headers, xhrFields, statusCode, dataType, contentType, timeout, global, } = mergedOptions;
|
|
917
|
+
// 需要发送的数据
|
|
918
|
+
// GET/HEAD 请求和 processData 为 true 时,转换为查询字符串格式,特殊格式不转换
|
|
919
|
+
const isMethodQueryString = isQueryStringData(method);
|
|
920
|
+
if (data &&
|
|
921
|
+
(isMethodQueryString || processData) &&
|
|
922
|
+
!isString(data) &&
|
|
923
|
+
!(data instanceof ArrayBuffer) &&
|
|
924
|
+
!(data instanceof Blob) &&
|
|
925
|
+
!(data instanceof Document) &&
|
|
926
|
+
!(data instanceof FormData)) {
|
|
927
|
+
data = param(data);
|
|
928
|
+
}
|
|
929
|
+
// 对于 GET、HEAD 类型的请求,把 data 数据添加到 URL 中
|
|
930
|
+
if (data && isMethodQueryString) {
|
|
931
|
+
// 查询字符串拼接到 URL 中
|
|
932
|
+
url = appendQuery(url, data);
|
|
933
|
+
data = null;
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* 触发事件和回调函数
|
|
937
|
+
* @param event
|
|
938
|
+
* @param callback
|
|
939
|
+
* @param args
|
|
940
|
+
*/
|
|
941
|
+
const trigger = (event, callback, ...args) => {
|
|
942
|
+
// 触发全局事件
|
|
943
|
+
if (global) {
|
|
944
|
+
$(document).trigger(event, callback === 'success' ? successEventParams : eventParams);
|
|
945
|
+
}
|
|
946
|
+
// 触发 ajax 回调和事件
|
|
947
|
+
let resultGlobal;
|
|
948
|
+
let resultCustom;
|
|
949
|
+
// 全局回调
|
|
950
|
+
if (callback in globalOptions) {
|
|
951
|
+
// @ts-ignore
|
|
952
|
+
resultGlobal = globalOptions[callback](...args);
|
|
953
|
+
}
|
|
954
|
+
// 自定义回调
|
|
955
|
+
if (mergedOptions[callback]) {
|
|
956
|
+
// @ts-ignore
|
|
957
|
+
resultCustom = mergedOptions[callback](...args);
|
|
958
|
+
}
|
|
959
|
+
// beforeSend 回调返回 false 时取消 ajax 请求
|
|
960
|
+
if (callback === 'beforeSend' &&
|
|
961
|
+
[resultGlobal, resultCustom].includes(false)) {
|
|
962
|
+
isCanceled = true;
|
|
963
|
+
}
|
|
964
|
+
};
|
|
965
|
+
// XMLHttpRequest 请求
|
|
966
|
+
const XHR = () => {
|
|
967
|
+
let textStatus;
|
|
968
|
+
return new Promise((resolve, reject) => {
|
|
969
|
+
const doReject = (reason) => {
|
|
970
|
+
return reject(new Error(reason));
|
|
971
|
+
};
|
|
972
|
+
// GET/HEAD 请求的缓存处理
|
|
973
|
+
if (isMethodQueryString && !cache) {
|
|
974
|
+
url = appendQuery(url, `_=${Date.now()}`);
|
|
975
|
+
}
|
|
976
|
+
// 创建 XHR
|
|
977
|
+
const xhr = new XMLHttpRequest();
|
|
978
|
+
xhr.open(method, url, async, username, password);
|
|
979
|
+
if (contentType ||
|
|
980
|
+
(data && !isMethodQueryString && contentType !== false)) {
|
|
981
|
+
xhr.setRequestHeader('Content-Type', contentType);
|
|
982
|
+
}
|
|
983
|
+
// 设置 Accept
|
|
984
|
+
if (dataType === 'json') {
|
|
985
|
+
xhr.setRequestHeader('Accept', 'application/json, text/javascript');
|
|
986
|
+
}
|
|
987
|
+
// 添加 headers
|
|
988
|
+
eachObject(headers, (key, value) => {
|
|
989
|
+
// undefined 值不发送,string 和 null 需要发送
|
|
990
|
+
if (!isUndefined(value)) {
|
|
991
|
+
xhr.setRequestHeader(key, value + ''); // 把 null 转换成字符串
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
// 检查是否是跨域请求,跨域请求时不添加 X-Requested-With
|
|
995
|
+
if (!isCrossDomain(url)) {
|
|
996
|
+
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
|
997
|
+
}
|
|
998
|
+
// 设置 xhr 选项
|
|
999
|
+
eachObject(xhrFields, (key, value) => {
|
|
1000
|
+
xhr[key] = value;
|
|
1001
|
+
});
|
|
1002
|
+
eventParams.xhr = successEventParams.xhr = xhr;
|
|
1003
|
+
eventParams.options = successEventParams.options = mergedOptions;
|
|
1004
|
+
let xhrTimeout;
|
|
1005
|
+
xhr.onload = () => {
|
|
1006
|
+
if (xhrTimeout) {
|
|
1007
|
+
clearTimeout(xhrTimeout);
|
|
1008
|
+
}
|
|
1009
|
+
// AJAX 返回的 HTTP 响应码是否表示成功
|
|
1010
|
+
const isSuccess = isHttpStatusSuccess(xhr.status);
|
|
1011
|
+
// @ts-ignore
|
|
1012
|
+
let responseData = undefined;
|
|
1013
|
+
if (isSuccess) {
|
|
1014
|
+
textStatus =
|
|
1015
|
+
xhr.status === 204 || method === 'HEAD'
|
|
1016
|
+
? 'nocontent'
|
|
1017
|
+
: xhr.status === 304
|
|
1018
|
+
? 'notmodified'
|
|
1019
|
+
: 'success';
|
|
1020
|
+
if (dataType === 'json' ||
|
|
1021
|
+
(!dataType &&
|
|
1022
|
+
(xhr.getResponseHeader('content-type') || '').includes('json'))) {
|
|
1023
|
+
try {
|
|
1024
|
+
responseData =
|
|
1025
|
+
method === 'HEAD' ? undefined : JSON.parse(xhr.responseText);
|
|
1026
|
+
successEventParams.response = responseData;
|
|
1027
|
+
}
|
|
1028
|
+
catch (err) {
|
|
1029
|
+
textStatus = 'parsererror';
|
|
1030
|
+
trigger(ajaxError, 'error', xhr, textStatus);
|
|
1031
|
+
doReject(textStatus);
|
|
1032
|
+
}
|
|
1033
|
+
if (textStatus !== 'parsererror') {
|
|
1034
|
+
trigger(ajaxSuccess, 'success', responseData, textStatus, xhr);
|
|
1035
|
+
resolve(responseData);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
else {
|
|
1039
|
+
responseData =
|
|
1040
|
+
method === 'HEAD'
|
|
1041
|
+
? undefined
|
|
1042
|
+
: xhr.responseType === 'text' || xhr.responseType === ''
|
|
1043
|
+
? xhr.responseText
|
|
1044
|
+
: xhr.response;
|
|
1045
|
+
successEventParams.response = responseData;
|
|
1046
|
+
trigger(ajaxSuccess, 'success', responseData, textStatus, xhr);
|
|
1047
|
+
resolve(responseData);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
else {
|
|
1051
|
+
textStatus = 'error';
|
|
1052
|
+
trigger(ajaxError, 'error', xhr, textStatus);
|
|
1053
|
+
doReject(textStatus);
|
|
1054
|
+
}
|
|
1055
|
+
// statusCode
|
|
1056
|
+
eachArray([globalOptions.statusCode ?? {}, statusCode], (func) => {
|
|
1057
|
+
if (func[xhr.status]) {
|
|
1058
|
+
if (isSuccess) {
|
|
1059
|
+
func[xhr.status](responseData, textStatus, xhr);
|
|
1060
|
+
}
|
|
1061
|
+
else {
|
|
1062
|
+
func[xhr.status](xhr, textStatus);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1066
|
+
trigger(ajaxComplete, 'complete', xhr, textStatus);
|
|
1067
|
+
};
|
|
1068
|
+
xhr.onerror = () => {
|
|
1069
|
+
if (xhrTimeout) {
|
|
1070
|
+
clearTimeout(xhrTimeout);
|
|
1071
|
+
}
|
|
1072
|
+
trigger(ajaxError, 'error', xhr, xhr.statusText);
|
|
1073
|
+
trigger(ajaxComplete, 'complete', xhr, 'error');
|
|
1074
|
+
doReject(xhr.statusText);
|
|
1075
|
+
};
|
|
1076
|
+
xhr.onabort = () => {
|
|
1077
|
+
let statusText = 'abort';
|
|
1078
|
+
if (xhrTimeout) {
|
|
1079
|
+
statusText = 'timeout';
|
|
1080
|
+
clearTimeout(xhrTimeout);
|
|
1081
|
+
}
|
|
1082
|
+
trigger(ajaxError, 'error', xhr, statusText);
|
|
1083
|
+
trigger(ajaxComplete, 'complete', xhr, statusText);
|
|
1084
|
+
doReject(statusText);
|
|
1085
|
+
};
|
|
1086
|
+
// ajax start 回调
|
|
1087
|
+
trigger(ajaxStart, 'beforeSend', xhr, mergedOptions);
|
|
1088
|
+
if (isCanceled) {
|
|
1089
|
+
return doReject('cancel');
|
|
1090
|
+
}
|
|
1091
|
+
// Timeout
|
|
1092
|
+
if (timeout > 0) {
|
|
1093
|
+
xhrTimeout = window.setTimeout(() => xhr.abort(), timeout);
|
|
1094
|
+
}
|
|
1095
|
+
// 发送 XHR
|
|
1096
|
+
xhr.send(data);
|
|
1097
|
+
});
|
|
1098
|
+
};
|
|
1099
|
+
return XHR();
|
|
1100
|
+
};
|
|
1101
|
+
|
|
1102
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
1103
|
+
class MduiElement extends h {
|
|
1104
|
+
/**
|
|
1105
|
+
* 触发自定义事件。若返回 false,表示事件被取消
|
|
1106
|
+
* @param type
|
|
1107
|
+
* @param options 通常只用到 cancelable 和 detail;bubbles、composed 统一不用
|
|
1108
|
+
*/
|
|
1109
|
+
emit(type, options) {
|
|
1110
|
+
const event = new CustomEvent(type, Object.assign({
|
|
1111
|
+
bubbles: true,
|
|
1112
|
+
cancelable: false,
|
|
1113
|
+
composed: true,
|
|
1114
|
+
detail: {},
|
|
1115
|
+
}, options));
|
|
1116
|
+
return this.dispatchEvent(event);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
/**
|
|
1121
|
+
* 检查指定的 slot 是否存在
|
|
1122
|
+
*/
|
|
1123
|
+
class HasSlotController {
|
|
1124
|
+
constructor(host, ...slotNames) {
|
|
1125
|
+
this.slotNames = [];
|
|
1126
|
+
(this.host = host).addController(this);
|
|
1127
|
+
this.slotNames = slotNames;
|
|
1128
|
+
this.onSlotChange = this.onSlotChange.bind(this);
|
|
1129
|
+
}
|
|
1130
|
+
hostConnected() {
|
|
1131
|
+
this.host.shadowRoot.addEventListener('slotchange', this.onSlotChange);
|
|
1132
|
+
if (!isDomReady()) {
|
|
1133
|
+
$(() => {
|
|
1134
|
+
this.host.requestUpdate();
|
|
1135
|
+
});
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
hostDisconnected() {
|
|
1139
|
+
this.host.shadowRoot.removeEventListener('slotchange', this.onSlotChange);
|
|
1140
|
+
}
|
|
1141
|
+
test(slotName) {
|
|
1142
|
+
return slotName === '[default]'
|
|
1143
|
+
? this.hasDefaultSlot()
|
|
1144
|
+
: this.hasNamedSlot(slotName);
|
|
1145
|
+
}
|
|
1146
|
+
hasDefaultSlot() {
|
|
1147
|
+
return [...this.host.childNodes].some((node) => {
|
|
1148
|
+
if (node.nodeType === node.TEXT_NODE && node.textContent.trim() !== '') {
|
|
1149
|
+
return true;
|
|
1150
|
+
}
|
|
1151
|
+
if (node.nodeType === node.ELEMENT_NODE) {
|
|
1152
|
+
const el = node;
|
|
1153
|
+
if (!el.hasAttribute('slot')) {
|
|
1154
|
+
return true;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
return false;
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
hasNamedSlot(name) {
|
|
1161
|
+
return this.host.querySelector(`:scope > [slot="${name}"]`) !== null;
|
|
1162
|
+
}
|
|
1163
|
+
onSlotChange(event) {
|
|
1164
|
+
const slot = event.target;
|
|
1165
|
+
if ((this.slotNames.includes('[default]') && !slot.name) ||
|
|
1166
|
+
(slot.name && this.slotNames.includes(slot.name))) {
|
|
1167
|
+
this.host.requestUpdate();
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
const componentStyle = i$2 `:host{box-sizing:border-box}:host *,:host ::after,:host ::before{box-sizing:inherit}:host :focus,:host :focus-visible,:host(:focus),:host(:focus-visible){outline:0}[hidden]{display:none!important}`;
|
|
1173
|
+
|
|
1174
|
+
const style$2 = i$2 `:host{display:inline-block;width:1em;height:1em;font-weight:400;font-family:'Material Icons';font-display:block;font-style:normal;line-height:1;direction:ltr;letter-spacing:normal;white-space:nowrap;text-transform:none;word-wrap:normal;-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;-moz-osx-font-smoothing:grayscale;font-size:1.5rem}::slotted(svg),svg{width:100%;height:100%;fill:currentcolor}`;
|
|
1175
|
+
|
|
1176
|
+
/**
|
|
1177
|
+
* @summary 图标组件
|
|
1178
|
+
*
|
|
1179
|
+
* ```html
|
|
1180
|
+
* <mdui-icon name="search"></mdui-icon>
|
|
1181
|
+
* ```
|
|
1182
|
+
*
|
|
1183
|
+
* @slot - `svg` 图标的内容
|
|
1184
|
+
*/
|
|
1185
|
+
let Icon = class Icon extends MduiElement {
|
|
1186
|
+
constructor() {
|
|
1187
|
+
super(...arguments);
|
|
1188
|
+
this.hasSlotController = new HasSlotController(this, '[default]');
|
|
1189
|
+
}
|
|
1190
|
+
render() {
|
|
1191
|
+
const renderDefault = () => {
|
|
1192
|
+
if (this.name) {
|
|
1193
|
+
const [name, variant] = this.name.split('--');
|
|
1194
|
+
const familyMap = new Map([
|
|
1195
|
+
['outlined', 'Material Icons Outlined'],
|
|
1196
|
+
['filled', 'Material Icons'],
|
|
1197
|
+
['rounded', 'Material Icons Round'],
|
|
1198
|
+
['sharp', 'Material Icons Sharp'],
|
|
1199
|
+
['two-tone', 'Material Icons Two Tone'],
|
|
1200
|
+
]);
|
|
1201
|
+
return ke `<span style="${se({ fontFamily: familyMap.get(variant) })}">${name}</span>`;
|
|
1202
|
+
}
|
|
1203
|
+
if (this.src) {
|
|
1204
|
+
return ke `${be(ajax({ url: this.src }).then(fe))}`;
|
|
1205
|
+
}
|
|
1206
|
+
return ke ``;
|
|
1207
|
+
};
|
|
1208
|
+
return this.hasSlotController.test('[default]')
|
|
1209
|
+
? ke `<slot></slot>`
|
|
1210
|
+
: renderDefault();
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
Icon.styles = [componentStyle, style$2];
|
|
1214
|
+
__decorate([
|
|
1215
|
+
n({ reflect: true })
|
|
1216
|
+
], Icon.prototype, "name", void 0);
|
|
1217
|
+
__decorate([
|
|
1218
|
+
n({ reflect: true })
|
|
1219
|
+
], Icon.prototype, "src", void 0);
|
|
1220
|
+
Icon = __decorate([
|
|
1221
|
+
t$1('mdui-icon')
|
|
1222
|
+
], Icon);
|
|
1223
|
+
|
|
1224
|
+
/**
|
|
1225
|
+
* @license
|
|
1226
|
+
* Copyright 2018 Google LLC
|
|
1227
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
1228
|
+
*/const to=t=>t??D;
|
|
1229
|
+
|
|
1230
|
+
function cc(names) {
|
|
1231
|
+
if (typeof names === "string" || typeof names === "number") return "" + names
|
|
1232
|
+
|
|
1233
|
+
let out = "";
|
|
1234
|
+
|
|
1235
|
+
if (Array.isArray(names)) {
|
|
1236
|
+
for (let i = 0, tmp; i < names.length; i++) {
|
|
1237
|
+
if ((tmp = cc(names[i])) !== "") {
|
|
1238
|
+
out += (out && " ") + tmp;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
} else {
|
|
1242
|
+
for (let k in names) {
|
|
1243
|
+
if (names[k]) out += (out && " ") + k;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
return out
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
/**
|
|
1251
|
+
* 获取属性值
|
|
1252
|
+
* @param element
|
|
1253
|
+
* @param key 属性键名
|
|
1254
|
+
* @param defaultValue 当 element.getAttribute 为 null 时,默认返回 undefined
|
|
1255
|
+
*/
|
|
1256
|
+
const getAttribute = (element, key, defaultValue) => {
|
|
1257
|
+
const value = element.getAttribute(key);
|
|
1258
|
+
return isNull(value) ? defaultValue : value;
|
|
1259
|
+
};
|
|
1260
|
+
/**
|
|
1261
|
+
* 移除属性
|
|
1262
|
+
* @param element
|
|
1263
|
+
* @param key 属性键名
|
|
1264
|
+
*/
|
|
1265
|
+
const removeAttribute = (element, key) => {
|
|
1266
|
+
element.removeAttribute(key);
|
|
1267
|
+
};
|
|
1268
|
+
/**
|
|
1269
|
+
* 设置属性值
|
|
1270
|
+
* @param element
|
|
1271
|
+
* @param key 属性键名
|
|
1272
|
+
* @param value 值,若为 null,则调用 removeAttribute
|
|
1273
|
+
*/
|
|
1274
|
+
const setAttribute = (element, key, value) => {
|
|
1275
|
+
isNull(value)
|
|
1276
|
+
? removeAttribute(element, key)
|
|
1277
|
+
: element.setAttribute(key, value);
|
|
1278
|
+
};
|
|
1279
|
+
|
|
1280
|
+
/**
|
|
1281
|
+
* 获取元素的样式值
|
|
1282
|
+
* @param element
|
|
1283
|
+
* @param name
|
|
1284
|
+
*/
|
|
1285
|
+
const getComputedStyleValue = (element, name) => {
|
|
1286
|
+
const window = getWindow();
|
|
1287
|
+
return window.getComputedStyle(element).getPropertyValue(toKebabCase(name));
|
|
1288
|
+
};
|
|
1289
|
+
/**
|
|
1290
|
+
* 检查元素的 box-sizing 是否是 border-box
|
|
1291
|
+
* @param element
|
|
1292
|
+
*/
|
|
1293
|
+
const isBorderBox = (element) => {
|
|
1294
|
+
return getComputedStyleValue(element, 'box-sizing') === 'border-box';
|
|
1295
|
+
};
|
|
1296
|
+
/**
|
|
1297
|
+
* 获取元素的 padding, border, margin 宽度(两侧宽度的和,单位为px)
|
|
1298
|
+
* @param element
|
|
1299
|
+
* @param direction
|
|
1300
|
+
* @param extra
|
|
1301
|
+
*/
|
|
1302
|
+
const getExtraWidth = (element, direction, extra) => {
|
|
1303
|
+
const position = direction === 'width'
|
|
1304
|
+
? ['Left', 'Right']
|
|
1305
|
+
: ['Top', 'Bottom'];
|
|
1306
|
+
return [0, 1].reduce((prev, _, index) => {
|
|
1307
|
+
let prop = extra + position[index];
|
|
1308
|
+
if (extra === 'border') {
|
|
1309
|
+
prop += 'Width';
|
|
1310
|
+
}
|
|
1311
|
+
return prev + parseFloat(getComputedStyleValue(element, prop) || '0');
|
|
1312
|
+
}, 0);
|
|
1313
|
+
};
|
|
1314
|
+
/**
|
|
1315
|
+
* 获取元素的样式值,对 width 和 height 进行过处理
|
|
1316
|
+
* @param element
|
|
1317
|
+
* @param name
|
|
1318
|
+
*/
|
|
1319
|
+
const getStyle = (element, name) => {
|
|
1320
|
+
// width、height 属性使用 getComputedStyle 得到的值不准确,需要使用 getBoundingClientRect 获取
|
|
1321
|
+
if (name === 'width' || name === 'height') {
|
|
1322
|
+
const valueNumber = element.getBoundingClientRect()[name];
|
|
1323
|
+
if (isBorderBox(element)) {
|
|
1324
|
+
return `${valueNumber}px`;
|
|
1325
|
+
}
|
|
1326
|
+
return `${valueNumber -
|
|
1327
|
+
getExtraWidth(element, name, 'border') -
|
|
1328
|
+
getExtraWidth(element, name, 'padding')}px`;
|
|
1329
|
+
}
|
|
1330
|
+
return getComputedStyleValue(element, name);
|
|
1331
|
+
};
|
|
1332
|
+
/**
|
|
1333
|
+
* 数值单位的 CSS 属性
|
|
1334
|
+
*/
|
|
1335
|
+
const cssNumber = [
|
|
1336
|
+
'animation-iteration-count',
|
|
1337
|
+
'column-count',
|
|
1338
|
+
'fill-opacity',
|
|
1339
|
+
'flex-grow',
|
|
1340
|
+
'flex-shrink',
|
|
1341
|
+
'font-weight',
|
|
1342
|
+
'grid-area',
|
|
1343
|
+
'grid-column',
|
|
1344
|
+
'grid-column-end',
|
|
1345
|
+
'grid-column-start',
|
|
1346
|
+
'grid-row',
|
|
1347
|
+
'grid-row-end',
|
|
1348
|
+
'grid-row-start',
|
|
1349
|
+
'line-height',
|
|
1350
|
+
'opacity',
|
|
1351
|
+
'order',
|
|
1352
|
+
'orphans',
|
|
1353
|
+
'widows',
|
|
1354
|
+
'z-index',
|
|
1355
|
+
'zoom',
|
|
1356
|
+
];
|
|
1357
|
+
|
|
1358
|
+
eachArray(['attr', 'prop', 'css'], (name, nameIndex) => {
|
|
1359
|
+
// eslint-disable-next-line
|
|
1360
|
+
const set = (element, key, value) => {
|
|
1361
|
+
// 值为 undefined 时,不修改
|
|
1362
|
+
if (isUndefined(value)) {
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
// attr
|
|
1366
|
+
if (nameIndex === 0) {
|
|
1367
|
+
return setAttribute(element, key, value);
|
|
1368
|
+
}
|
|
1369
|
+
// prop
|
|
1370
|
+
if (nameIndex === 1) {
|
|
1371
|
+
// @ts-ignore
|
|
1372
|
+
element[key] = value;
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
// css
|
|
1376
|
+
key = toKebabCase(key);
|
|
1377
|
+
// 获取默认后缀。以 -- 开头的为 CSS 变量,不添加后缀;值为数值类型的不添加后缀
|
|
1378
|
+
const getSuffix = () => key.startsWith('--') || cssNumber.includes(key) ? '' : 'px';
|
|
1379
|
+
element.style.setProperty(key, isNumber(value) ? `${value}${getSuffix()}` : value);
|
|
1380
|
+
};
|
|
1381
|
+
// eslint-disable-next-line
|
|
1382
|
+
const get = (element, key) => {
|
|
1383
|
+
// attr
|
|
1384
|
+
if (nameIndex === 0) {
|
|
1385
|
+
// 属性不存在时,原生 getAttribute 方法返回 null,而 jquery 返回 undefined。这里和 jquery 保持一致
|
|
1386
|
+
return getAttribute(element, key);
|
|
1387
|
+
}
|
|
1388
|
+
// prop
|
|
1389
|
+
if (nameIndex === 1) {
|
|
1390
|
+
// @ts-ignore
|
|
1391
|
+
return element[key];
|
|
1392
|
+
}
|
|
1393
|
+
return getStyle(element, key);
|
|
1394
|
+
};
|
|
1395
|
+
$.fn[name] = function (key,
|
|
1396
|
+
// eslint-disable-next-line
|
|
1397
|
+
value) {
|
|
1398
|
+
if (isObjectLike(key)) {
|
|
1399
|
+
eachObject(key, (k, v) => {
|
|
1400
|
+
// @ts-ignore
|
|
1401
|
+
this[name](k, v);
|
|
1402
|
+
});
|
|
1403
|
+
return this;
|
|
1404
|
+
}
|
|
1405
|
+
if (arguments.length === 1) {
|
|
1406
|
+
const element = this[0];
|
|
1407
|
+
return isElement(element) ? get(element, key) : undefined;
|
|
1408
|
+
}
|
|
1409
|
+
return this.each((i, element) => {
|
|
1410
|
+
set(element, key, isFunction(value) ? value.call(element, i, get(element, key)) : value);
|
|
1411
|
+
});
|
|
1412
|
+
};
|
|
1413
|
+
});
|
|
1414
|
+
|
|
1415
|
+
/**
|
|
1416
|
+
* 使用该 WeakMap 来存储指定表单中所有的 mdui 表单控件
|
|
1417
|
+
* 在每个表单控件的 hostConnected 中添加、hostDisconnected 中移除对应表单的 mdui 表单控件,
|
|
1418
|
+
* 然后在 getFormControls 方法中就能获取到表单中所有的 mdui 表单控件
|
|
1419
|
+
*/
|
|
1420
|
+
const formCollections = new WeakMap();
|
|
1421
|
+
/**
|
|
1422
|
+
* 获取表单中的所有表单控件,包含原生和 mdui 表单控件
|
|
1423
|
+
* 原生的 `HTMLFormElement.elements` 仅返回原生表单控件,不包含 mdui 表单控件
|
|
1424
|
+
*/
|
|
1425
|
+
const getFormControls = (form) => {
|
|
1426
|
+
const nativeFormControls = [...form.elements];
|
|
1427
|
+
const formControls = formCollections.get(form) || [];
|
|
1428
|
+
const comparePosition = (a, b) => {
|
|
1429
|
+
const position = a.compareDocumentPosition(b);
|
|
1430
|
+
return position & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
|
|
1431
|
+
};
|
|
1432
|
+
// 按 DOM 元素的顺序排序
|
|
1433
|
+
return [...nativeFormControls, ...formControls].sort(comparePosition);
|
|
1434
|
+
};
|
|
1435
|
+
|
|
1436
|
+
/**
|
|
1437
|
+
* 过滤掉数组中的重复元素
|
|
1438
|
+
* @param arr 数组
|
|
1439
|
+
* @example
|
|
1440
|
+
```js
|
|
1441
|
+
unique([1, 2, 12, 3, 2, 1, 2, 1, 1]);
|
|
1442
|
+
// [1, 2, 12, 3]
|
|
1443
|
+
```
|
|
1444
|
+
*/
|
|
1445
|
+
const unique = (arr) => {
|
|
1446
|
+
return [...new Set(arr)];
|
|
1447
|
+
};
|
|
1448
|
+
|
|
1449
|
+
/**
|
|
1450
|
+
* 判断组件是否定义完成
|
|
1451
|
+
*
|
|
1452
|
+
* 如果需要在组件操作或读取组件外部、或组件 slot 中的原生 DOM 时,则需要在 DOM 就绪时,才能认为组件定义完成
|
|
1453
|
+
* 如果组件需要和其他组件配合使用,则需要等待其他组件定义完成后,才能认为组件定义完成
|
|
1454
|
+
*/
|
|
1455
|
+
class DefinedController {
|
|
1456
|
+
constructor(host, options) {
|
|
1457
|
+
/**
|
|
1458
|
+
* 组件是否已定义完成
|
|
1459
|
+
*/
|
|
1460
|
+
this.defined = false;
|
|
1461
|
+
(this.host = host).addController(this);
|
|
1462
|
+
this.relatedElements = options.relatedElements;
|
|
1463
|
+
this.needDomReady = options.needDomReady || !!options.relatedElements;
|
|
1464
|
+
this.onSlotChange = this.onSlotChange.bind(this);
|
|
1465
|
+
}
|
|
1466
|
+
hostConnected() {
|
|
1467
|
+
this.host.shadowRoot.addEventListener('slotchange', this.onSlotChange);
|
|
1468
|
+
}
|
|
1469
|
+
hostDisconnected() {
|
|
1470
|
+
this.host.shadowRoot.removeEventListener('slotchange', this.onSlotChange);
|
|
1471
|
+
}
|
|
1472
|
+
/**
|
|
1473
|
+
* 判断组件是否定义完成
|
|
1474
|
+
*/
|
|
1475
|
+
isDefined() {
|
|
1476
|
+
if (this.defined) {
|
|
1477
|
+
return true;
|
|
1478
|
+
}
|
|
1479
|
+
this.defined =
|
|
1480
|
+
(!this.needDomReady || isDomReady()) &&
|
|
1481
|
+
!this.getUndefinedLocalNames().length;
|
|
1482
|
+
return this.defined;
|
|
1483
|
+
}
|
|
1484
|
+
/**
|
|
1485
|
+
* 在组件定义完成后,promise 被 resolve
|
|
1486
|
+
*/
|
|
1487
|
+
async whenDefined() {
|
|
1488
|
+
if (this.defined) {
|
|
1489
|
+
return Promise.resolve();
|
|
1490
|
+
}
|
|
1491
|
+
const document = getDocument();
|
|
1492
|
+
if (this.needDomReady && !isDomReady(document)) {
|
|
1493
|
+
await new Promise((resolve) => {
|
|
1494
|
+
document.addEventListener('DOMContentLoaded', () => resolve(), {
|
|
1495
|
+
once: true,
|
|
1496
|
+
});
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
const undefinedLocalNames = this.getUndefinedLocalNames();
|
|
1500
|
+
if (undefinedLocalNames.length) {
|
|
1501
|
+
const promises = [];
|
|
1502
|
+
undefinedLocalNames.forEach((localName) => {
|
|
1503
|
+
promises.push(customElements.whenDefined(localName));
|
|
1504
|
+
});
|
|
1505
|
+
await Promise.all(promises);
|
|
1506
|
+
}
|
|
1507
|
+
this.defined = true;
|
|
1508
|
+
return;
|
|
1509
|
+
}
|
|
1510
|
+
/**
|
|
1511
|
+
* slot 中的未完成定义的相关 Web components 组件的 CSS 选择器
|
|
1512
|
+
*/
|
|
1513
|
+
getScopeLocalNameSelector() {
|
|
1514
|
+
const localNames = this.relatedElements;
|
|
1515
|
+
if (!localNames) {
|
|
1516
|
+
return null;
|
|
1517
|
+
}
|
|
1518
|
+
if (Array.isArray(localNames)) {
|
|
1519
|
+
return localNames
|
|
1520
|
+
.map((localName) => `${localName}:not(:defined)`)
|
|
1521
|
+
.join(',');
|
|
1522
|
+
}
|
|
1523
|
+
return Object.keys(localNames)
|
|
1524
|
+
.filter((localName) => !localNames[localName])
|
|
1525
|
+
.map((localName) => `${localName}:not(:defined)`)
|
|
1526
|
+
.join(',');
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1529
|
+
* 整个页面中的未完成定义的相关 Web components 组件的 CSS 选择器
|
|
1530
|
+
*/
|
|
1531
|
+
getGlobalLocalNameSelector() {
|
|
1532
|
+
const localNames = this.relatedElements;
|
|
1533
|
+
if (!localNames || Array.isArray(localNames)) {
|
|
1534
|
+
return null;
|
|
1535
|
+
}
|
|
1536
|
+
return Object.keys(localNames)
|
|
1537
|
+
.filter((localName) => localNames[localName])
|
|
1538
|
+
.map((localName) => `${localName}:not(:defined)`)
|
|
1539
|
+
.join(',');
|
|
1540
|
+
}
|
|
1541
|
+
/**
|
|
1542
|
+
* 获取未完成定义的相关 Web components 组件名
|
|
1543
|
+
*/
|
|
1544
|
+
getUndefinedLocalNames() {
|
|
1545
|
+
const scopeSelector = this.getScopeLocalNameSelector();
|
|
1546
|
+
const globalSelector = this.getGlobalLocalNameSelector();
|
|
1547
|
+
const undefinedScopeElements = scopeSelector
|
|
1548
|
+
? [...this.host.querySelectorAll(scopeSelector)]
|
|
1549
|
+
: [];
|
|
1550
|
+
const undefinedGlobalElements = globalSelector
|
|
1551
|
+
? [...getDocument().querySelectorAll(globalSelector)]
|
|
1552
|
+
: [];
|
|
1553
|
+
const localNames = [
|
|
1554
|
+
...undefinedScopeElements,
|
|
1555
|
+
...undefinedGlobalElements,
|
|
1556
|
+
].map((element) => element.localName);
|
|
1557
|
+
return unique(localNames);
|
|
1558
|
+
}
|
|
1559
|
+
/**
|
|
1560
|
+
* slot 变更时,若 slot 中包含未完成定义的相关 Web components 组件,则组件未定义完成
|
|
1561
|
+
*/
|
|
1562
|
+
onSlotChange() {
|
|
1563
|
+
const selector = this.getScopeLocalNameSelector();
|
|
1564
|
+
if (selector) {
|
|
1565
|
+
const undefinedElements = this.host.querySelectorAll(selector);
|
|
1566
|
+
if (undefinedElements.length) {
|
|
1567
|
+
this.defined = false;
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
/**
|
|
1574
|
+
* 参考:https://github.com/shoelace-style/shoelace/blob/next/src/internal/form.ts
|
|
1575
|
+
*/
|
|
1576
|
+
/**
|
|
1577
|
+
* 在执行 `<form>` 元素的 reportValidity() 时,不会执行 mdui 组件的 reportValidity() 方法,
|
|
1578
|
+
* 因此在 mdui 表单控件的 hostConnected 中把 `<form>` 的 reportValidity 替换为自定义方法,
|
|
1579
|
+
* hostDisconnected 中恢复为 原生 reportValidity 方法
|
|
1580
|
+
*
|
|
1581
|
+
* 该 WeakMap 用于存储指定 `<form>` 的原生 reportValidity 方法
|
|
1582
|
+
*
|
|
1583
|
+
* 日后使用 ElementInternals 可不再进行该处理,但当前 safari 浏览器不支持。
|
|
1584
|
+
*/
|
|
1585
|
+
const reportValidityOverloads = new WeakMap();
|
|
1586
|
+
/**
|
|
1587
|
+
* 在执行表单的 reset() 方法后,使用该 WeakMap 存储指定表单中所有的表单控件
|
|
1588
|
+
* 在表单控件中监听值变更后,需要从该 WeakMap 中判断是否存在该表单控件,
|
|
1589
|
+
* 若存在,则 invalid 设置为 false(不显示验证不通过样式),同时从 WeakMap 中移除该表单控件
|
|
1590
|
+
*/
|
|
1591
|
+
const formResets = new WeakMap();
|
|
1592
|
+
class FormController {
|
|
1593
|
+
constructor(host, options) {
|
|
1594
|
+
(this.host = host).addController(this);
|
|
1595
|
+
this.definedController = new DefinedController(host, {
|
|
1596
|
+
needDomReady: true,
|
|
1597
|
+
});
|
|
1598
|
+
this.options = {
|
|
1599
|
+
form: (control) => {
|
|
1600
|
+
const formId = $(control).attr('form');
|
|
1601
|
+
if (formId) {
|
|
1602
|
+
const root = control.getRootNode();
|
|
1603
|
+
return root.getElementById(formId);
|
|
1604
|
+
}
|
|
1605
|
+
return control.closest('form');
|
|
1606
|
+
},
|
|
1607
|
+
name: (control) => control.name,
|
|
1608
|
+
value: (control) => control.value,
|
|
1609
|
+
defaultValue: (control) => control.defaultValue,
|
|
1610
|
+
setValue: (control, value) => (control.value = value),
|
|
1611
|
+
disabled: (control) => control.disabled,
|
|
1612
|
+
reportValidity: (control) => isFunction(control.reportValidity) ? control.reportValidity() : true,
|
|
1613
|
+
...options,
|
|
1614
|
+
};
|
|
1615
|
+
this.onFormData = this.onFormData.bind(this);
|
|
1616
|
+
this.onFormSubmit = this.onFormSubmit.bind(this);
|
|
1617
|
+
this.onFormReset = this.onFormReset.bind(this);
|
|
1618
|
+
this.reportFormValidity = this.reportFormValidity.bind(this);
|
|
1619
|
+
}
|
|
1620
|
+
hostConnected() {
|
|
1621
|
+
this.definedController.whenDefined().then(() => {
|
|
1622
|
+
this.form = this.options.form(this.host);
|
|
1623
|
+
if (this.form) {
|
|
1624
|
+
this.attachForm(this.form);
|
|
1625
|
+
}
|
|
1626
|
+
});
|
|
1627
|
+
}
|
|
1628
|
+
hostDisconnected() {
|
|
1629
|
+
this.detachForm();
|
|
1630
|
+
}
|
|
1631
|
+
hostUpdated() {
|
|
1632
|
+
this.definedController.whenDefined().then(() => {
|
|
1633
|
+
const form = this.options.form(this.host);
|
|
1634
|
+
if (!form) {
|
|
1635
|
+
this.detachForm();
|
|
1636
|
+
}
|
|
1637
|
+
if (form && this.form !== form) {
|
|
1638
|
+
this.detachForm();
|
|
1639
|
+
this.attachForm(form);
|
|
1640
|
+
}
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
/**
|
|
1644
|
+
* 获取当前表单控件关联的 `<form>` 元素
|
|
1645
|
+
*/
|
|
1646
|
+
getForm() {
|
|
1647
|
+
return this.form ?? null;
|
|
1648
|
+
}
|
|
1649
|
+
/**
|
|
1650
|
+
* 重置整个表单,所有表单控件恢复成默认值
|
|
1651
|
+
*/
|
|
1652
|
+
reset(invoker) {
|
|
1653
|
+
this.doAction('reset', invoker);
|
|
1654
|
+
}
|
|
1655
|
+
/**
|
|
1656
|
+
* 提交整个表单
|
|
1657
|
+
*/
|
|
1658
|
+
submit(invoker) {
|
|
1659
|
+
this.doAction('submit', invoker);
|
|
1660
|
+
}
|
|
1661
|
+
attachForm(form) {
|
|
1662
|
+
if (!form) {
|
|
1663
|
+
this.form = undefined;
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
this.form = form;
|
|
1667
|
+
if (formCollections.has(this.form)) {
|
|
1668
|
+
formCollections.get(this.form).add(this.host);
|
|
1669
|
+
}
|
|
1670
|
+
else {
|
|
1671
|
+
formCollections.set(this.form, new Set([this.host]));
|
|
1672
|
+
}
|
|
1673
|
+
this.form.addEventListener('formdata', this.onFormData);
|
|
1674
|
+
this.form.addEventListener('submit', this.onFormSubmit);
|
|
1675
|
+
this.form.addEventListener('reset', this.onFormReset);
|
|
1676
|
+
if (!reportValidityOverloads.has(this.form)) {
|
|
1677
|
+
reportValidityOverloads.set(this.form, this.form.reportValidity);
|
|
1678
|
+
this.form.reportValidity = () => this.reportFormValidity();
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
detachForm() {
|
|
1682
|
+
if (this.form) {
|
|
1683
|
+
formCollections.get(this.form).delete(this.host);
|
|
1684
|
+
this.form.removeEventListener('formdata', this.onFormData);
|
|
1685
|
+
this.form.removeEventListener('submit', this.onFormSubmit);
|
|
1686
|
+
this.form.removeEventListener('reset', this.onFormReset);
|
|
1687
|
+
if (reportValidityOverloads.has(this.form) &&
|
|
1688
|
+
!formCollections.get(this.form).size) {
|
|
1689
|
+
this.form.reportValidity = reportValidityOverloads.get(this.form);
|
|
1690
|
+
reportValidityOverloads.delete(this.form);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
doAction(type, invoker) {
|
|
1695
|
+
if (!this.form) {
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
const $button = $(`<button type="${type}">`).css({
|
|
1699
|
+
position: 'absolute',
|
|
1700
|
+
width: 0,
|
|
1701
|
+
height: 0,
|
|
1702
|
+
clipPath: 'inset(50%)',
|
|
1703
|
+
overflow: 'hidden',
|
|
1704
|
+
whiteSpace: 'nowrap',
|
|
1705
|
+
});
|
|
1706
|
+
const button = $button[0];
|
|
1707
|
+
if (invoker) {
|
|
1708
|
+
button.name = invoker.name;
|
|
1709
|
+
button.value = invoker.value;
|
|
1710
|
+
[
|
|
1711
|
+
'formaction',
|
|
1712
|
+
'formenctype',
|
|
1713
|
+
'formmethod',
|
|
1714
|
+
'formnovalidate',
|
|
1715
|
+
'formtarget',
|
|
1716
|
+
].forEach((attr) => {
|
|
1717
|
+
$button.attr(attr, $(invoker).attr(attr));
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1720
|
+
this.form.append(button);
|
|
1721
|
+
button.click();
|
|
1722
|
+
button.remove();
|
|
1723
|
+
}
|
|
1724
|
+
onFormData(event) {
|
|
1725
|
+
const disabled = this.options.disabled(this.host);
|
|
1726
|
+
const name = this.options.name(this.host);
|
|
1727
|
+
const value = this.options.value(this.host);
|
|
1728
|
+
// 对于按钮,仅在 type="submit" 时,才提交值。已在 doAction() 方法中把 name、value 注入到 <button> 元素上
|
|
1729
|
+
const isButton = [
|
|
1730
|
+
'mdui-button',
|
|
1731
|
+
'mdui-button-icon',
|
|
1732
|
+
'mdui-chip',
|
|
1733
|
+
'mdui-fab',
|
|
1734
|
+
'mdui-segmented-button',
|
|
1735
|
+
].includes(this.host.tagName.toLowerCase());
|
|
1736
|
+
if (!disabled &&
|
|
1737
|
+
!isButton &&
|
|
1738
|
+
isString(name) &&
|
|
1739
|
+
name &&
|
|
1740
|
+
!isUndefined(value)) {
|
|
1741
|
+
if (Array.isArray(value)) {
|
|
1742
|
+
value.forEach((val) => {
|
|
1743
|
+
event.formData.append(name, val.toString());
|
|
1744
|
+
});
|
|
1745
|
+
}
|
|
1746
|
+
else {
|
|
1747
|
+
event.formData.append(name, value.toString());
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
// todo: 当前组件进行验证的顺序,取决于组件的注册顺序,而不会按在 DOM 中的顺序从上到下验证。如何按 DOM 顺序验证?
|
|
1752
|
+
onFormSubmit(event) {
|
|
1753
|
+
const disabled = this.options.disabled(this.host);
|
|
1754
|
+
const reportValidity = this.options.reportValidity;
|
|
1755
|
+
if (this.form &&
|
|
1756
|
+
!this.form.noValidate &&
|
|
1757
|
+
!disabled &&
|
|
1758
|
+
!reportValidity(this.host)) {
|
|
1759
|
+
event.preventDefault();
|
|
1760
|
+
event.stopImmediatePropagation();
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
onFormReset() {
|
|
1764
|
+
if (this.form) {
|
|
1765
|
+
this.options.setValue(this.host, this.options.defaultValue(this.host));
|
|
1766
|
+
// 取消 invalid 状态。
|
|
1767
|
+
// 此外,还需要在各个组件内,监听值的变更,判断 formResets 中是否存在当前表单控件。若存在则 invalid 设为 false;不存在则设置为 checkValidity() 的值
|
|
1768
|
+
// @ts-ignore
|
|
1769
|
+
this.host.invalid = false;
|
|
1770
|
+
if (formResets.has(this.form)) {
|
|
1771
|
+
formResets.get(this.form).add(this.host);
|
|
1772
|
+
}
|
|
1773
|
+
else {
|
|
1774
|
+
formResets.set(this.form, new Set([this.host]));
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
reportFormValidity() {
|
|
1779
|
+
if (this.form && !this.form.noValidate) {
|
|
1780
|
+
const elements = getFormControls(this.form);
|
|
1781
|
+
for (const element of elements) {
|
|
1782
|
+
if (isFunction(element.reportValidity) && !element.reportValidity()) {
|
|
1783
|
+
return false;
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
return true;
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
const AnchorMixin = (superclass) => {
|
|
1792
|
+
class AnchorMixinClass extends superclass {
|
|
1793
|
+
renderAnchor({ id, className, part, content = ke `<slot></slot>`, refDirective, tabIndex, }) {
|
|
1794
|
+
return ke `<a ${refDirective} id="${to(id)}" class="_a ${className ? className : ''}" part="${to(part)}" href="${to(this.href)}" download="${to(this.download)}" target="${to(this.target)}" rel="${to(this.rel)}" tabindex="${to(tabIndex)}">${content}</a>`;
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
__decorate([
|
|
1798
|
+
n({ reflect: true })
|
|
1799
|
+
], AnchorMixinClass.prototype, "href", void 0);
|
|
1800
|
+
__decorate([
|
|
1801
|
+
n({ reflect: true })
|
|
1802
|
+
], AnchorMixinClass.prototype, "download", void 0);
|
|
1803
|
+
__decorate([
|
|
1804
|
+
n({ reflect: true })
|
|
1805
|
+
], AnchorMixinClass.prototype, "target", void 0);
|
|
1806
|
+
__decorate([
|
|
1807
|
+
n({ reflect: true })
|
|
1808
|
+
], AnchorMixinClass.prototype, "rel", void 0);
|
|
1809
|
+
return AnchorMixinClass;
|
|
1810
|
+
};
|
|
1811
|
+
|
|
1812
|
+
$.fn.removeAttr = function (attributeName) {
|
|
1813
|
+
const names = attributeName.split(' ').filter((name) => name);
|
|
1814
|
+
return this.each(function () {
|
|
1815
|
+
eachArray(names, (name) => {
|
|
1816
|
+
removeAttribute(this, name);
|
|
1817
|
+
});
|
|
1818
|
+
});
|
|
1819
|
+
};
|
|
1820
|
+
|
|
1821
|
+
let isClick = true;
|
|
1822
|
+
const document$1 = getDocument();
|
|
1823
|
+
document$1.addEventListener('pointerdown', () => {
|
|
1824
|
+
isClick = true;
|
|
1825
|
+
});
|
|
1826
|
+
document$1.addEventListener('keydown', () => {
|
|
1827
|
+
isClick = false;
|
|
1828
|
+
});
|
|
1829
|
+
/**
|
|
1830
|
+
* 参考:https://github.com/adobe/spectrum-web-components/blob/main/tools/shared/src/focusable.ts
|
|
1831
|
+
*/
|
|
1832
|
+
const FocusableMixin = (superclass) => {
|
|
1833
|
+
class FocusableMixinClass extends superclass {
|
|
1834
|
+
constructor() {
|
|
1835
|
+
super(...arguments);
|
|
1836
|
+
/**
|
|
1837
|
+
* 是否在页面加载完成后自动获取焦点
|
|
1838
|
+
*/
|
|
1839
|
+
this.autofocus = false;
|
|
1840
|
+
/**
|
|
1841
|
+
* 是否获得了焦点,不管是鼠标点击,还是键盘切换获得的焦点,都会添加该属性
|
|
1842
|
+
* 添加到 :host 元素上,供 CSS 选择器添加样式
|
|
1843
|
+
*/
|
|
1844
|
+
this.focused = false;
|
|
1845
|
+
/**
|
|
1846
|
+
* 是否通过键盘切换获得了焦点
|
|
1847
|
+
* 添加到 :host 元素上,供 CSS 选择器添加样式
|
|
1848
|
+
*/
|
|
1849
|
+
this.focusVisible = false;
|
|
1850
|
+
this.focusableDefinedController = new DefinedController(this, { relatedElements: [''] });
|
|
1851
|
+
this._manipulatingTabindex = false;
|
|
1852
|
+
this._tabIndex = 0;
|
|
1853
|
+
}
|
|
1854
|
+
/**
|
|
1855
|
+
* 元素在使用 Tab 键切换焦点时的顺序
|
|
1856
|
+
*/
|
|
1857
|
+
get tabIndex() {
|
|
1858
|
+
const $this = $(this);
|
|
1859
|
+
if (this.focusElement === this) {
|
|
1860
|
+
return Number($this.attr('tabindex') || -1);
|
|
1861
|
+
}
|
|
1862
|
+
const tabIndexAttribute = Number($this.attr('tabindex') || 0);
|
|
1863
|
+
if (this.focusDisabled || tabIndexAttribute < 0) {
|
|
1864
|
+
return -1;
|
|
1865
|
+
}
|
|
1866
|
+
if (!this.focusElement) {
|
|
1867
|
+
return tabIndexAttribute;
|
|
1868
|
+
}
|
|
1869
|
+
return this.focusElement.tabIndex;
|
|
1870
|
+
}
|
|
1871
|
+
set tabIndex(tabIndex) {
|
|
1872
|
+
if (this._manipulatingTabindex) {
|
|
1873
|
+
this._manipulatingTabindex = false;
|
|
1874
|
+
return;
|
|
1875
|
+
}
|
|
1876
|
+
const $this = $(this);
|
|
1877
|
+
if (this.focusElement === this) {
|
|
1878
|
+
if (tabIndex !== null) {
|
|
1879
|
+
this._tabIndex = tabIndex;
|
|
1880
|
+
}
|
|
1881
|
+
$this.attr('tabindex', this.focusDisabled ? null : tabIndex);
|
|
1882
|
+
return;
|
|
1883
|
+
}
|
|
1884
|
+
const onPointerDown = () => {
|
|
1885
|
+
if (this.tabIndex === -1) {
|
|
1886
|
+
this.tabIndex = 0;
|
|
1887
|
+
this.focus({ preventScroll: true });
|
|
1888
|
+
}
|
|
1889
|
+
};
|
|
1890
|
+
if (tabIndex === -1) {
|
|
1891
|
+
this.addEventListener('pointerdown', onPointerDown);
|
|
1892
|
+
}
|
|
1893
|
+
else {
|
|
1894
|
+
this._manipulatingTabindex = true;
|
|
1895
|
+
this.removeEventListener('pointerdown', onPointerDown);
|
|
1896
|
+
}
|
|
1897
|
+
if (tabIndex === -1 || this.focusDisabled) {
|
|
1898
|
+
$this.attr('tabindex', -1);
|
|
1899
|
+
if (tabIndex !== -1) {
|
|
1900
|
+
this.manageFocusElementTabindex(tabIndex);
|
|
1901
|
+
}
|
|
1902
|
+
return;
|
|
1903
|
+
}
|
|
1904
|
+
if (!this.hasAttribute('tabindex')) {
|
|
1905
|
+
this._manipulatingTabindex = false;
|
|
1906
|
+
}
|
|
1907
|
+
this.manageFocusElementTabindex(tabIndex);
|
|
1908
|
+
}
|
|
1909
|
+
/**
|
|
1910
|
+
* 父类要实现该属性,表示是否禁用 focus 状态
|
|
1911
|
+
*/
|
|
1912
|
+
get focusDisabled() {
|
|
1913
|
+
throw new Error('Must implement focusDisabled getter!');
|
|
1914
|
+
}
|
|
1915
|
+
/**
|
|
1916
|
+
* 最终获得焦点的元素
|
|
1917
|
+
*/
|
|
1918
|
+
get focusElement() {
|
|
1919
|
+
throw new Error('Must implement focusElement getter!');
|
|
1920
|
+
}
|
|
1921
|
+
connectedCallback() {
|
|
1922
|
+
super.connectedCallback();
|
|
1923
|
+
this.updateComplete.then(() => {
|
|
1924
|
+
requestAnimationFrame(() => {
|
|
1925
|
+
this.manageAutoFocus();
|
|
1926
|
+
});
|
|
1927
|
+
});
|
|
1928
|
+
}
|
|
1929
|
+
/**
|
|
1930
|
+
* 模拟鼠标点击元素
|
|
1931
|
+
*/
|
|
1932
|
+
click() {
|
|
1933
|
+
if (this.focusDisabled) {
|
|
1934
|
+
return;
|
|
1935
|
+
}
|
|
1936
|
+
if (this.focusElement !== this) {
|
|
1937
|
+
this.focusElement.click();
|
|
1938
|
+
}
|
|
1939
|
+
else {
|
|
1940
|
+
HTMLElement.prototype.click.apply(this);
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
/**
|
|
1944
|
+
* 将焦点设置到当前元素。
|
|
1945
|
+
*
|
|
1946
|
+
* 可以传入一个对象作为参数,该对象的属性包括:
|
|
1947
|
+
*
|
|
1948
|
+
* * `preventScroll`:默认情况下,元素获取焦点后,页面会滚动以将该元素滚动到视图中。如果不希望页面滚动,可以将此属性设置为 `true`。
|
|
1949
|
+
*/
|
|
1950
|
+
focus(options) {
|
|
1951
|
+
if (this.focusDisabled || !this.focusElement) {
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
if (this.focusElement !== this) {
|
|
1955
|
+
this.focusElement.focus(options);
|
|
1956
|
+
}
|
|
1957
|
+
else {
|
|
1958
|
+
HTMLElement.prototype.focus.apply(this, [options]);
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
/**
|
|
1962
|
+
* 移除当前元素的焦点
|
|
1963
|
+
*/
|
|
1964
|
+
blur() {
|
|
1965
|
+
if (this.focusElement !== this) {
|
|
1966
|
+
this.focusElement.blur();
|
|
1967
|
+
}
|
|
1968
|
+
else {
|
|
1969
|
+
HTMLElement.prototype.blur.apply(this);
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
firstUpdated(changedProperties) {
|
|
1973
|
+
super.firstUpdated(changedProperties);
|
|
1974
|
+
this.focusElement.addEventListener('focus', () => {
|
|
1975
|
+
this.focused = true;
|
|
1976
|
+
this.focusVisible = !isClick;
|
|
1977
|
+
});
|
|
1978
|
+
this.focusElement.addEventListener('blur', () => {
|
|
1979
|
+
this.focused = false;
|
|
1980
|
+
this.focusVisible = false;
|
|
1981
|
+
});
|
|
1982
|
+
}
|
|
1983
|
+
update(changedProperties) {
|
|
1984
|
+
if (this._lastFocusDisabled === undefined ||
|
|
1985
|
+
this._lastFocusDisabled !== this.focusDisabled) {
|
|
1986
|
+
this._lastFocusDisabled = this.focusDisabled;
|
|
1987
|
+
const $this = $(this);
|
|
1988
|
+
if (this.focusDisabled) {
|
|
1989
|
+
$this.removeAttr('tabindex');
|
|
1990
|
+
}
|
|
1991
|
+
else {
|
|
1992
|
+
if (this.focusElement === this) {
|
|
1993
|
+
this._manipulatingTabindex = true;
|
|
1994
|
+
$this.attr('tabindex', this._tabIndex);
|
|
1995
|
+
}
|
|
1996
|
+
else if (this.tabIndex > -1) {
|
|
1997
|
+
$this.removeAttr('tabindex');
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
super.update(changedProperties);
|
|
2002
|
+
}
|
|
2003
|
+
updated(changedProperties) {
|
|
2004
|
+
super.updated(changedProperties);
|
|
2005
|
+
if (this.focused && this.focusDisabled) {
|
|
2006
|
+
this.blur();
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
async manageFocusElementTabindex(tabIndex) {
|
|
2010
|
+
if (!this.focusElement) {
|
|
2011
|
+
await this.updateComplete;
|
|
2012
|
+
}
|
|
2013
|
+
if (tabIndex === null) {
|
|
2014
|
+
this.focusElement.removeAttribute('tabindex');
|
|
2015
|
+
}
|
|
2016
|
+
else {
|
|
2017
|
+
this.focusElement.tabIndex = tabIndex;
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
manageAutoFocus() {
|
|
2021
|
+
if (this.autofocus) {
|
|
2022
|
+
this.dispatchEvent(new KeyboardEvent('keydown', {
|
|
2023
|
+
code: 'Tab',
|
|
2024
|
+
}));
|
|
2025
|
+
this.focusElement.focus();
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
__decorate([
|
|
2030
|
+
n({
|
|
2031
|
+
type: Boolean,
|
|
2032
|
+
/**
|
|
2033
|
+
* 哪些属性需要 reflect: true?
|
|
2034
|
+
* 一般所有属性都需要 reflect,但以下情况除外:
|
|
2035
|
+
* 1. 会频繁变更的属性
|
|
2036
|
+
* 2. 属性同步会造成较大性能开销的属性
|
|
2037
|
+
* 3. 复杂类型属性(数组、对象等,仅提供 property,不提供 attribute)
|
|
2038
|
+
*/
|
|
2039
|
+
reflect: true,
|
|
2040
|
+
converter: booleanConverter,
|
|
2041
|
+
})
|
|
2042
|
+
], FocusableMixinClass.prototype, "autofocus", void 0);
|
|
2043
|
+
__decorate([
|
|
2044
|
+
n({
|
|
2045
|
+
type: Boolean,
|
|
2046
|
+
reflect: true,
|
|
2047
|
+
converter: booleanConverter,
|
|
2048
|
+
})
|
|
2049
|
+
], FocusableMixinClass.prototype, "focused", void 0);
|
|
2050
|
+
__decorate([
|
|
2051
|
+
n({
|
|
2052
|
+
type: Boolean,
|
|
2053
|
+
reflect: true,
|
|
2054
|
+
converter: booleanConverter,
|
|
2055
|
+
attribute: 'focus-visible',
|
|
2056
|
+
})
|
|
2057
|
+
], FocusableMixinClass.prototype, "focusVisible", void 0);
|
|
2058
|
+
__decorate([
|
|
2059
|
+
n({ type: Number, attribute: 'tabindex' })
|
|
2060
|
+
], FocusableMixinClass.prototype, "tabIndex", null);
|
|
2061
|
+
return FocusableMixinClass;
|
|
2062
|
+
};
|
|
2063
|
+
|
|
2064
|
+
/**
|
|
2065
|
+
* @license
|
|
2066
|
+
* Copyright 2018 Google LLC
|
|
2067
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
2068
|
+
*/const Rt=e(class extends i{constructor(s){if(super(s),s.type!==t.ATTRIBUTE||"class"!==s.name||s.strings?.length>2)throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute.")}render(t){return " "+Object.keys(t).filter((s=>t[s])).join(" ")+" "}update(t,[s]){if(void 0===this.st){this.st=new Set,void 0!==t.strings&&(this.nt=new Set(t.strings.join(" ").split(/\s/).filter((t=>""!==t))));for(const t in s)s[t]&&!this.nt?.has(t)&&this.st.add(t);return this.render(s)}const i=t.element.classList;for(const t of this.st)t in s||(i.remove(t),this.st.delete(t));for(const t in s){const r=!!s[t];r===this.st.has(t)||this.nt?.has(t)||(r?(i.add(t),this.st.add(t)):(i.remove(t),this.st.delete(t)));}return R}});
|
|
2069
|
+
|
|
2070
|
+
const style$1 = i$2 `:host{position:relative;display:inline-block;flex-shrink:0;width:2.5rem;height:2.5rem;stroke:rgb(var(--mdui-color-primary))}.progress{position:relative;display:inline-block;width:100%;height:100%;text-align:left;transition:opacity var(--mdui-motion-duration-medium1) var(--mdui-motion-easing-linear)}.determinate svg{transform:rotate(-90deg);fill:transparent}.determinate .track{stroke:transparent}.determinate .circle{stroke:inherit;transition:stroke-dashoffset var(--mdui-motion-duration-long2) var(--mdui-motion-easing-standard)}.indeterminate{font-size:0;letter-spacing:0;white-space:nowrap;animation:mdui-comp-circular-progress-rotate 1568ms var(--mdui-motion-easing-linear) infinite}.indeterminate .circle,.indeterminate .layer{position:absolute;width:100%;height:100%}.indeterminate .layer{animation:mdui-comp-circular-progress-layer-rotate 5332ms var(--mdui-motion-easing-standard) infinite both}.indeterminate .circle{fill:transparent;stroke:inherit}.indeterminate .gap-patch{position:absolute;top:0;left:47.5%;width:5%;height:100%;overflow:hidden}.indeterminate .gap-patch .circle{left:-900%;width:2000%;transform:rotate(180deg)}.indeterminate .clipper{position:relative;display:inline-block;width:50%;height:100%;overflow:hidden}.indeterminate .clipper .circle{width:200%}.indeterminate .clipper.left .circle{animation:mdui-comp-circular-progress-left-spin 1333ms var(--mdui-motion-easing-standard) infinite both}.indeterminate .clipper.right .circle{left:-100%;animation:mdui-comp-circular-progress-right-spin 1333ms var(--mdui-motion-easing-standard) infinite both}@keyframes mdui-comp-circular-progress-rotate{to{transform:rotate(360deg)}}@keyframes mdui-comp-circular-progress-layer-rotate{12.5%{transform:rotate(135deg)}25%{transform:rotate(270deg)}37.5%{transform:rotate(405deg)}50%{transform:rotate(540deg)}62.5%{transform:rotate(675deg)}75%{transform:rotate(810deg)}87.5%{transform:rotate(945deg)}100%{transform:rotate(1080deg)}}@keyframes mdui-comp-circular-progress-left-spin{0%{transform:rotate(265deg)}50%{transform:rotate(130deg)}100%{transform:rotate(265deg)}}@keyframes mdui-comp-circular-progress-right-spin{0%{transform:rotate(-265deg)}50%{transform:rotate(-130deg)}100%{transform:rotate(-265deg)}}`;
|
|
2071
|
+
|
|
2072
|
+
/**
|
|
2073
|
+
* @summary 圆形进度指示器组件
|
|
2074
|
+
*
|
|
2075
|
+
* ```html
|
|
2076
|
+
* <mdui-circular-progress></mdui-circular-progress>
|
|
2077
|
+
* ```
|
|
2078
|
+
*/
|
|
2079
|
+
let CircularProgress = class CircularProgress extends MduiElement {
|
|
2080
|
+
constructor() {
|
|
2081
|
+
super(...arguments);
|
|
2082
|
+
/**
|
|
2083
|
+
* 进度指示器的最大值。默认为 `1`
|
|
2084
|
+
*/
|
|
2085
|
+
this.max = 1;
|
|
2086
|
+
}
|
|
2087
|
+
render() {
|
|
2088
|
+
const isDeterminate = !isUndefined(this.value);
|
|
2089
|
+
return ke `<div class="progress ${Rt({
|
|
2090
|
+
determinate: isDeterminate,
|
|
2091
|
+
indeterminate: !isDeterminate,
|
|
2092
|
+
})}">${isDeterminate ? this.renderDeterminate() : this.renderInDeterminate()}</div>`;
|
|
2093
|
+
}
|
|
2094
|
+
renderDeterminate() {
|
|
2095
|
+
const value = this.value;
|
|
2096
|
+
const strokeWidth = 4; // 圆环宽度
|
|
2097
|
+
const circleRadius = 18; // 圆环宽度中心点的半径
|
|
2098
|
+
const π = 3.1415926;
|
|
2099
|
+
const center = circleRadius + strokeWidth / 2;
|
|
2100
|
+
const circumference = 2 * π * circleRadius;
|
|
2101
|
+
const determinateStrokeDashOffset = (1 - value / Math.max(this.max ?? value, value)) * circumference;
|
|
2102
|
+
return ke `<svg viewBox="0 0 ${center * 2} ${center * 2}"><circle class="track" cx="${center}" cy="${center}" r="${circleRadius}" stroke-width="${strokeWidth}"></circle><circle class="circle" cx="${center}" cy="${center}" r="${circleRadius}" stroke-dasharray="${2 * π * circleRadius}" stroke-dashoffset="${determinateStrokeDashOffset}" stroke-width="${strokeWidth}"></circle></svg>`;
|
|
2103
|
+
}
|
|
2104
|
+
renderInDeterminate() {
|
|
2105
|
+
const strokeWidth = 4; // 圆环宽度
|
|
2106
|
+
const circleRadius = 18; // 圆环宽度中心点的半径
|
|
2107
|
+
const π = 3.1415926;
|
|
2108
|
+
const center = circleRadius + strokeWidth / 2;
|
|
2109
|
+
const circumference = 2 * π * circleRadius;
|
|
2110
|
+
const halfCircumference = 0.5 * circumference;
|
|
2111
|
+
const circle = (thisStrokeWidth) => ke `<svg class="circle" viewBox="0 0 ${center * 2} ${center * 2}"><circle cx="${center}" cy="${center}" r="${circleRadius}" stroke-dasharray="${circumference}" stroke-dashoffset="${halfCircumference}" stroke-width="${thisStrokeWidth}"></circle></svg>`;
|
|
2112
|
+
return ke `<div class="layer"><div class="clipper left">${circle(strokeWidth)}</div><div class="gap-patch">${circle(strokeWidth * 0.8)}</div><div class="clipper right">${circle(strokeWidth)}</div></div>`;
|
|
2113
|
+
}
|
|
2114
|
+
};
|
|
2115
|
+
CircularProgress.styles = [componentStyle, style$1];
|
|
2116
|
+
__decorate([
|
|
2117
|
+
n({ type: Number, reflect: true })
|
|
2118
|
+
], CircularProgress.prototype, "max", void 0);
|
|
2119
|
+
__decorate([
|
|
2120
|
+
n({ type: Number })
|
|
2121
|
+
], CircularProgress.prototype, "value", void 0);
|
|
2122
|
+
CircularProgress = __decorate([
|
|
2123
|
+
t$1('mdui-circular-progress')
|
|
2124
|
+
], CircularProgress);
|
|
2125
|
+
|
|
2126
|
+
// eslint-disable-next-line
|
|
2127
|
+
$.fn.is = function (selector) {
|
|
2128
|
+
let isMatched = false;
|
|
2129
|
+
if (isFunction(selector)) {
|
|
2130
|
+
this.each((index, element) => {
|
|
2131
|
+
if (selector.call(element, index, element)) {
|
|
2132
|
+
isMatched = true;
|
|
2133
|
+
}
|
|
2134
|
+
});
|
|
2135
|
+
return isMatched;
|
|
2136
|
+
}
|
|
2137
|
+
if (isString(selector)) {
|
|
2138
|
+
this.each((_, element) => {
|
|
2139
|
+
if (isDocument(element) || isWindow(element)) {
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
2142
|
+
if (element.matches.call(element, selector)) {
|
|
2143
|
+
isMatched = true;
|
|
2144
|
+
}
|
|
2145
|
+
});
|
|
2146
|
+
return isMatched;
|
|
2147
|
+
}
|
|
2148
|
+
const $compareWith = $(selector);
|
|
2149
|
+
this.each((_, element) => {
|
|
2150
|
+
$compareWith.each((_, compare) => {
|
|
2151
|
+
if (element === compare) {
|
|
2152
|
+
isMatched = true;
|
|
2153
|
+
}
|
|
2154
|
+
});
|
|
2155
|
+
});
|
|
2156
|
+
return isMatched;
|
|
2157
|
+
};
|
|
2158
|
+
|
|
2159
|
+
$.fn.children = function (selector) {
|
|
2160
|
+
const children = [];
|
|
2161
|
+
this.each((_, element) => {
|
|
2162
|
+
eachArray(element.childNodes, (childNode) => {
|
|
2163
|
+
if (!isElement(childNode)) {
|
|
2164
|
+
return;
|
|
2165
|
+
}
|
|
2166
|
+
if (!selector || $(childNode).is(selector)) {
|
|
2167
|
+
children.push(childNode);
|
|
2168
|
+
}
|
|
2169
|
+
});
|
|
2170
|
+
});
|
|
2171
|
+
return new JQ(unique(children));
|
|
2172
|
+
};
|
|
2173
|
+
|
|
2174
|
+
$.fn.slice = function (...args) {
|
|
2175
|
+
return new JQ([].slice.apply(this, args));
|
|
2176
|
+
};
|
|
2177
|
+
|
|
2178
|
+
$.fn.eq = function (index) {
|
|
2179
|
+
const ret = index === -1 ? this.slice(index) : this.slice(index, +index + 1);
|
|
2180
|
+
return new JQ(ret);
|
|
2181
|
+
};
|
|
2182
|
+
|
|
2183
|
+
const dir = ($elements, nameIndex, node,
|
|
2184
|
+
// eslint-disable-next-line
|
|
2185
|
+
selector, filter) => {
|
|
2186
|
+
const ret = [];
|
|
2187
|
+
let target;
|
|
2188
|
+
$elements.each((_, element) => {
|
|
2189
|
+
target = element[node];
|
|
2190
|
+
// 不能包含最顶层的 document 元素
|
|
2191
|
+
while (target && isElement(target)) {
|
|
2192
|
+
// prevUntil, nextUntil, parentsUntil
|
|
2193
|
+
if (nameIndex === 2) {
|
|
2194
|
+
if (selector && $(target).is(selector)) {
|
|
2195
|
+
break;
|
|
2196
|
+
}
|
|
2197
|
+
if (!filter || $(target).is(filter)) {
|
|
2198
|
+
ret.push(target);
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
// prev, next, parent
|
|
2202
|
+
else if (nameIndex === 0) {
|
|
2203
|
+
if (!selector || $(target).is(selector)) {
|
|
2204
|
+
ret.push(target);
|
|
2205
|
+
}
|
|
2206
|
+
break;
|
|
2207
|
+
}
|
|
2208
|
+
// prevAll, nextAll, parents
|
|
2209
|
+
else {
|
|
2210
|
+
if (!selector || $(target).is(selector)) {
|
|
2211
|
+
ret.push(target);
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
target = target[node];
|
|
2215
|
+
}
|
|
2216
|
+
});
|
|
2217
|
+
return new JQ(unique(ret));
|
|
2218
|
+
};
|
|
2219
|
+
|
|
2220
|
+
eachArray(['', 's', 'sUntil'], (name, nameIndex) => {
|
|
2221
|
+
$.fn[`parent${name}`] = function (
|
|
2222
|
+
// eslint-disable-next-line
|
|
2223
|
+
selector, filter) {
|
|
2224
|
+
// parents、parentsUntil 需要把元素的顺序反向处理,以便和 jQuery 的结果一致
|
|
2225
|
+
const $nodes = !nameIndex ? this : $(this.get().reverse());
|
|
2226
|
+
return dir($nodes, nameIndex, 'parentNode', selector, filter);
|
|
2227
|
+
};
|
|
2228
|
+
});
|
|
2229
|
+
|
|
2230
|
+
// eslint-disable-next-line
|
|
2231
|
+
$.fn.index = function (selector) {
|
|
2232
|
+
if (!arguments.length) {
|
|
2233
|
+
return this.eq(0).parent().children().get().indexOf(this[0]);
|
|
2234
|
+
}
|
|
2235
|
+
if (isString(selector)) {
|
|
2236
|
+
return $(selector).get().indexOf(this[0]);
|
|
2237
|
+
}
|
|
2238
|
+
return this.get().indexOf($(selector)[0]);
|
|
2239
|
+
};
|
|
2240
|
+
|
|
2241
|
+
eachArray(['add', 'remove', 'toggle'], (name) => {
|
|
2242
|
+
$.fn[`${name}Class`] = function (className) {
|
|
2243
|
+
if (name === 'remove' && !arguments.length) {
|
|
2244
|
+
return this.each((_, element) => {
|
|
2245
|
+
setAttribute(element, 'class', '');
|
|
2246
|
+
});
|
|
2247
|
+
}
|
|
2248
|
+
return this.each((i, element) => {
|
|
2249
|
+
if (!isElement(element)) {
|
|
2250
|
+
return;
|
|
2251
|
+
}
|
|
2252
|
+
const classes = (isFunction(className)
|
|
2253
|
+
? className.call(element, i, getAttribute(element, 'class', ''))
|
|
2254
|
+
: className)
|
|
2255
|
+
.split(' ')
|
|
2256
|
+
.filter((name) => name);
|
|
2257
|
+
eachArray(classes, (cls) => {
|
|
2258
|
+
element.classList[name](cls);
|
|
2259
|
+
});
|
|
2260
|
+
});
|
|
2261
|
+
};
|
|
2262
|
+
});
|
|
2263
|
+
|
|
2264
|
+
const weakMap = new WeakMap();
|
|
2265
|
+
/**
|
|
2266
|
+
* 获取元素上的所有数据
|
|
2267
|
+
* @param element
|
|
2268
|
+
*/
|
|
2269
|
+
const getAll = (element) => {
|
|
2270
|
+
return weakMap.get(element) ?? {};
|
|
2271
|
+
};
|
|
2272
|
+
/**
|
|
2273
|
+
* 获取元素上的的一个数据
|
|
2274
|
+
* @param element
|
|
2275
|
+
* @param keyOriginal
|
|
2276
|
+
*/
|
|
2277
|
+
const get$2 = (element, keyOriginal) => {
|
|
2278
|
+
const data = getAll(element);
|
|
2279
|
+
const key = toCamelCase(keyOriginal);
|
|
2280
|
+
return key in data ? data[key] : undefined;
|
|
2281
|
+
};
|
|
2282
|
+
/**
|
|
2283
|
+
* 在上设置键值对数据
|
|
2284
|
+
* @param element
|
|
2285
|
+
* @param object
|
|
2286
|
+
*/
|
|
2287
|
+
const setAll = (element, object) => {
|
|
2288
|
+
const data = getAll(element);
|
|
2289
|
+
eachObject(object, (keyOriginal, value) => {
|
|
2290
|
+
data[toCamelCase(keyOriginal)] = value;
|
|
2291
|
+
});
|
|
2292
|
+
weakMap.set(element, data);
|
|
2293
|
+
};
|
|
2294
|
+
/**
|
|
2295
|
+
* 在元素上设置一个数据
|
|
2296
|
+
* @param element
|
|
2297
|
+
* @param keyOriginal
|
|
2298
|
+
* @param value
|
|
2299
|
+
*/
|
|
2300
|
+
const set$2 = (element, keyOriginal, value) => {
|
|
2301
|
+
setAll(element, { [keyOriginal]: value });
|
|
2302
|
+
};
|
|
2303
|
+
const rbrace = /^(?:{[\w\W]*\}|\[[\w\W]*\])$/;
|
|
2304
|
+
/**
|
|
2305
|
+
* dataset 中的值读取时进行转换
|
|
2306
|
+
* @param value
|
|
2307
|
+
*/
|
|
2308
|
+
const stringTransform = (value) => {
|
|
2309
|
+
if (value === 'true') {
|
|
2310
|
+
return true;
|
|
2311
|
+
}
|
|
2312
|
+
if (value === 'false') {
|
|
2313
|
+
return false;
|
|
2314
|
+
}
|
|
2315
|
+
if (value === 'null') {
|
|
2316
|
+
return null;
|
|
2317
|
+
}
|
|
2318
|
+
if (value === +value + '') {
|
|
2319
|
+
return +value;
|
|
2320
|
+
}
|
|
2321
|
+
if (rbrace.test(value)) {
|
|
2322
|
+
return JSON.parse(value);
|
|
2323
|
+
}
|
|
2324
|
+
return value;
|
|
2325
|
+
};
|
|
2326
|
+
// 若 value 不存在,则从 `dataset` 中获取值。key 需要自行转为驼峰法
|
|
2327
|
+
const dataAttr = (element, key, value) => {
|
|
2328
|
+
if (isUndefined(value) && element.nodeType === 1) {
|
|
2329
|
+
value = element.dataset[key];
|
|
2330
|
+
if (isString(value)) {
|
|
2331
|
+
try {
|
|
2332
|
+
value = stringTransform(value);
|
|
2333
|
+
}
|
|
2334
|
+
catch (e) { }
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
return value;
|
|
2338
|
+
};
|
|
2339
|
+
|
|
2340
|
+
// eslint-disable-next-line
|
|
2341
|
+
$.fn.data = function (key, value) {
|
|
2342
|
+
// 获取所有值
|
|
2343
|
+
if (isUndefined(key)) {
|
|
2344
|
+
if (!this.length) {
|
|
2345
|
+
return undefined;
|
|
2346
|
+
}
|
|
2347
|
+
const element = this[0];
|
|
2348
|
+
const resultData = getAll(element);
|
|
2349
|
+
// window, document 上不存在 `dataset`
|
|
2350
|
+
if (element.nodeType !== 1) {
|
|
2351
|
+
return resultData;
|
|
2352
|
+
}
|
|
2353
|
+
// 若值未通过 data 方法设置,则从 `dataset` 中获取值。dataset 中读取的 key 会自动转为驼峰法
|
|
2354
|
+
eachObject(element.dataset, (key) => {
|
|
2355
|
+
resultData[key] = dataAttr(element, key, resultData[key]);
|
|
2356
|
+
});
|
|
2357
|
+
return resultData;
|
|
2358
|
+
}
|
|
2359
|
+
// 同时设置多个值
|
|
2360
|
+
if (isObjectLike(key)) {
|
|
2361
|
+
return this.each(function () {
|
|
2362
|
+
setAll(this, key);
|
|
2363
|
+
});
|
|
2364
|
+
}
|
|
2365
|
+
// value 传入了 undefined
|
|
2366
|
+
if (arguments.length === 2 && isUndefined(value)) {
|
|
2367
|
+
return this;
|
|
2368
|
+
}
|
|
2369
|
+
// 设置值
|
|
2370
|
+
if (!isUndefined(value)) {
|
|
2371
|
+
return this.each(function () {
|
|
2372
|
+
set$2(this, key, value);
|
|
2373
|
+
});
|
|
2374
|
+
}
|
|
2375
|
+
// 获取值
|
|
2376
|
+
if (!this.length) {
|
|
2377
|
+
return undefined;
|
|
2378
|
+
}
|
|
2379
|
+
return dataAttr(this[0], toCamelCase(key), get$2(this[0], key));
|
|
2380
|
+
};
|
|
2381
|
+
|
|
2382
|
+
// eslint-disable-next-line
|
|
2383
|
+
function each(target, callback) {
|
|
2384
|
+
// eachArray 回调函数是 value, key,这里的 each 函数是 key, value
|
|
2385
|
+
return isArrayLike(target)
|
|
2386
|
+
? eachArray(target, (value, index) => {
|
|
2387
|
+
return callback.call(value, index, value);
|
|
2388
|
+
})
|
|
2389
|
+
: eachObject(target, callback);
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
// eslint-disable-next-line
|
|
2393
|
+
function map(elements, callback) {
|
|
2394
|
+
const window = getWindow();
|
|
2395
|
+
let value;
|
|
2396
|
+
const ret = [];
|
|
2397
|
+
each(elements, (i, element) => {
|
|
2398
|
+
value = callback.call(window, element, i);
|
|
2399
|
+
if (value != null) {
|
|
2400
|
+
ret.push(value);
|
|
2401
|
+
}
|
|
2402
|
+
});
|
|
2403
|
+
return [].concat(...ret);
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
// eslint-disable-next-line
|
|
2407
|
+
$.fn.map = function (callback) {
|
|
2408
|
+
return new JQ(map(this, (element, i) => {
|
|
2409
|
+
return callback.call(element, i, element);
|
|
2410
|
+
}));
|
|
2411
|
+
};
|
|
2412
|
+
|
|
2413
|
+
// eslint-disable-next-line
|
|
2414
|
+
$.fn.filter = function (selector) {
|
|
2415
|
+
if (isFunction(selector)) {
|
|
2416
|
+
return this.map((index, element) => {
|
|
2417
|
+
return selector.call(element, index, element) ? element : undefined;
|
|
2418
|
+
});
|
|
2419
|
+
}
|
|
2420
|
+
if (isString(selector)) {
|
|
2421
|
+
return this.map((_, element) => {
|
|
2422
|
+
return $(element).is(selector) ? element : undefined;
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
const $selector = $(selector);
|
|
2426
|
+
return this.map((_, element) => {
|
|
2427
|
+
return $selector.get().includes(element) ? element : undefined;
|
|
2428
|
+
});
|
|
2429
|
+
};
|
|
2430
|
+
|
|
2431
|
+
/**
|
|
2432
|
+
* 值上面的 padding、border、margin 处理
|
|
2433
|
+
* @param element
|
|
2434
|
+
* @param name
|
|
2435
|
+
* @param value
|
|
2436
|
+
* @param funcIndex
|
|
2437
|
+
* @param includeMargin
|
|
2438
|
+
* @param multiply
|
|
2439
|
+
*/
|
|
2440
|
+
const handleExtraWidth = (element, name, value, funcIndex, includeMargin, multiply) => {
|
|
2441
|
+
// 获取元素的 padding, border, margin 宽度(两侧宽度的和)
|
|
2442
|
+
const getExtraWidthValue = (extra) => {
|
|
2443
|
+
return (getExtraWidth(element, name.toLowerCase(), extra) *
|
|
2444
|
+
multiply);
|
|
2445
|
+
};
|
|
2446
|
+
if (funcIndex === 2 && includeMargin) {
|
|
2447
|
+
value += getExtraWidthValue('margin');
|
|
2448
|
+
}
|
|
2449
|
+
if (isBorderBox(element)) {
|
|
2450
|
+
if (funcIndex === 0) {
|
|
2451
|
+
value -= getExtraWidthValue('border');
|
|
2452
|
+
}
|
|
2453
|
+
if (funcIndex === 1) {
|
|
2454
|
+
value -= getExtraWidthValue('border');
|
|
2455
|
+
value -= getExtraWidthValue('padding');
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
else {
|
|
2459
|
+
if (funcIndex === 0) {
|
|
2460
|
+
value += getExtraWidthValue('padding');
|
|
2461
|
+
}
|
|
2462
|
+
if (funcIndex === 2) {
|
|
2463
|
+
value += getExtraWidthValue('border');
|
|
2464
|
+
value += getExtraWidthValue('padding');
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
return value;
|
|
2468
|
+
};
|
|
2469
|
+
/**
|
|
2470
|
+
* 获取元素的样式值
|
|
2471
|
+
* @param element
|
|
2472
|
+
* @param name
|
|
2473
|
+
* @param funcIndex 0: innerWidth, innerHeight; 1: width, height; 2: outerWidth, outerHeight
|
|
2474
|
+
* @param includeMargin
|
|
2475
|
+
*/
|
|
2476
|
+
const get$1 = (element, name, funcIndex, includeMargin) => {
|
|
2477
|
+
const document = getDocument();
|
|
2478
|
+
const clientProp = `client${name}`;
|
|
2479
|
+
const scrollProp = `scroll${name}`;
|
|
2480
|
+
const offsetProp = `offset${name}`;
|
|
2481
|
+
const innerProp = `inner${name}`;
|
|
2482
|
+
// $(window).width()
|
|
2483
|
+
if (isWindow(element)) {
|
|
2484
|
+
// outerWidth, outerHeight 需要包含滚动条的宽度
|
|
2485
|
+
return funcIndex === 2
|
|
2486
|
+
? element[innerProp]
|
|
2487
|
+
: toElement(document)[clientProp];
|
|
2488
|
+
}
|
|
2489
|
+
// $(document).width()
|
|
2490
|
+
if (isDocument(element)) {
|
|
2491
|
+
const doc = toElement(element);
|
|
2492
|
+
return Math.max(
|
|
2493
|
+
// @ts-ignore
|
|
2494
|
+
element.body[scrollProp], doc[scrollProp],
|
|
2495
|
+
// @ts-ignore
|
|
2496
|
+
element.body[offsetProp], doc[offsetProp], doc[clientProp]);
|
|
2497
|
+
}
|
|
2498
|
+
const value = parseFloat(getComputedStyleValue(element, name.toLowerCase()) || '0');
|
|
2499
|
+
return handleExtraWidth(element, name, value, funcIndex, includeMargin, 1);
|
|
2500
|
+
};
|
|
2501
|
+
/**
|
|
2502
|
+
* 设置元素的样式值
|
|
2503
|
+
* @param element
|
|
2504
|
+
* @param elementIndex
|
|
2505
|
+
* @param name
|
|
2506
|
+
* @param funcIndex 0: innerWidth, innerHeight; 1: width, height; 2: outerWidth, outerHeight
|
|
2507
|
+
* @param includeMargin
|
|
2508
|
+
* @param value
|
|
2509
|
+
*/
|
|
2510
|
+
const set$1 = (element, elementIndex, name, funcIndex, includeMargin, value) => {
|
|
2511
|
+
let computedValue = isFunction(value)
|
|
2512
|
+
? value.call(element, elementIndex, get$1(element, name, funcIndex, includeMargin))
|
|
2513
|
+
: value;
|
|
2514
|
+
if (computedValue == null) {
|
|
2515
|
+
return;
|
|
2516
|
+
}
|
|
2517
|
+
const $element = $(element);
|
|
2518
|
+
const dimension = name.toLowerCase();
|
|
2519
|
+
// 特殊的值,不需要计算 padding、border、margin
|
|
2520
|
+
if (isString(computedValue) &&
|
|
2521
|
+
['auto', 'inherit', ''].includes(computedValue)) {
|
|
2522
|
+
$element.css(dimension, computedValue);
|
|
2523
|
+
return;
|
|
2524
|
+
}
|
|
2525
|
+
// 其他值保留原始单位。注意:如果不使用 px 作为单位,则算出的值一般是不准确的
|
|
2526
|
+
const suffix = computedValue.toString().replace(/\b[0-9.]*/, '');
|
|
2527
|
+
const numerical = parseFloat(computedValue);
|
|
2528
|
+
computedValue =
|
|
2529
|
+
handleExtraWidth(element, name, numerical, funcIndex, includeMargin, -1) +
|
|
2530
|
+
(suffix || 'px');
|
|
2531
|
+
$element.css(dimension, computedValue);
|
|
2532
|
+
};
|
|
2533
|
+
eachArray(['Width', 'Height'], (name) => {
|
|
2534
|
+
eachArray([`inner${name}`, name.toLowerCase(), `outer${name}`], (funcName, funcIndex) => {
|
|
2535
|
+
$.fn[funcName] = function (
|
|
2536
|
+
// eslint-disable-next-line
|
|
2537
|
+
margin,
|
|
2538
|
+
// eslint-disable-next-line
|
|
2539
|
+
value) {
|
|
2540
|
+
// 是否是赋值操作
|
|
2541
|
+
const isSet = arguments.length && (funcIndex < 2 || !isBoolean(margin));
|
|
2542
|
+
const includeMargin = margin === true || value === true;
|
|
2543
|
+
// 获取第一个元素的值
|
|
2544
|
+
if (!isSet) {
|
|
2545
|
+
return this.length
|
|
2546
|
+
? get$1(this[0], name, funcIndex, includeMargin)
|
|
2547
|
+
: undefined;
|
|
2548
|
+
}
|
|
2549
|
+
// 设置每个元素的值
|
|
2550
|
+
return this.each((index, element) => {
|
|
2551
|
+
return set$1(element, index, name, funcIndex, includeMargin, margin);
|
|
2552
|
+
});
|
|
2553
|
+
};
|
|
2554
|
+
});
|
|
2555
|
+
});
|
|
2556
|
+
|
|
2557
|
+
/**
|
|
2558
|
+
* 返回最近的用于定位的父元素
|
|
2559
|
+
*/
|
|
2560
|
+
$.fn.offsetParent = function () {
|
|
2561
|
+
const document = getDocument();
|
|
2562
|
+
return this.map(function () {
|
|
2563
|
+
let offsetParent = this.offsetParent;
|
|
2564
|
+
while (offsetParent && $(offsetParent).css('position') === 'static') {
|
|
2565
|
+
offsetParent = offsetParent.offsetParent;
|
|
2566
|
+
}
|
|
2567
|
+
return offsetParent || document.documentElement;
|
|
2568
|
+
});
|
|
2569
|
+
};
|
|
2570
|
+
|
|
2571
|
+
const floatStyle = ($element, name) => {
|
|
2572
|
+
return parseFloat($element.css(name));
|
|
2573
|
+
};
|
|
2574
|
+
// @ts-ignore
|
|
2575
|
+
$.fn.position = function () {
|
|
2576
|
+
if (!this.length) {
|
|
2577
|
+
return undefined;
|
|
2578
|
+
}
|
|
2579
|
+
const $element = this.eq(0);
|
|
2580
|
+
let currentOffset;
|
|
2581
|
+
let parentOffset = {
|
|
2582
|
+
left: 0,
|
|
2583
|
+
top: 0,
|
|
2584
|
+
};
|
|
2585
|
+
if ($element.css('position') === 'fixed') {
|
|
2586
|
+
currentOffset = $element[0].getBoundingClientRect();
|
|
2587
|
+
}
|
|
2588
|
+
else {
|
|
2589
|
+
currentOffset = $element.offset();
|
|
2590
|
+
const $offsetParent = $element.offsetParent();
|
|
2591
|
+
parentOffset = $offsetParent.offset();
|
|
2592
|
+
parentOffset.top += floatStyle($offsetParent, 'border-top-width');
|
|
2593
|
+
parentOffset.left += floatStyle($offsetParent, 'border-left-width');
|
|
2594
|
+
}
|
|
2595
|
+
return {
|
|
2596
|
+
top: currentOffset.top - parentOffset.top - floatStyle($element, 'margin-top'),
|
|
2597
|
+
left: currentOffset.left -
|
|
2598
|
+
parentOffset.left -
|
|
2599
|
+
floatStyle($element, 'margin-left'),
|
|
2600
|
+
};
|
|
2601
|
+
};
|
|
2602
|
+
|
|
2603
|
+
const get = (element) => {
|
|
2604
|
+
if (!element.getClientRects().length) {
|
|
2605
|
+
return { top: 0, left: 0 };
|
|
2606
|
+
}
|
|
2607
|
+
const { top, left } = element.getBoundingClientRect();
|
|
2608
|
+
const { pageYOffset, pageXOffset } = element.ownerDocument
|
|
2609
|
+
.defaultView;
|
|
2610
|
+
return {
|
|
2611
|
+
top: top + pageYOffset,
|
|
2612
|
+
left: left + pageXOffset,
|
|
2613
|
+
};
|
|
2614
|
+
};
|
|
2615
|
+
const set = (element, value, index) => {
|
|
2616
|
+
const $element = $(element);
|
|
2617
|
+
const position = $element.css('position');
|
|
2618
|
+
if (position === 'static') {
|
|
2619
|
+
$element.css('position', 'relative');
|
|
2620
|
+
}
|
|
2621
|
+
const currentOffset = get(element);
|
|
2622
|
+
const currentTopString = $element.css('top');
|
|
2623
|
+
const currentLeftString = $element.css('left');
|
|
2624
|
+
let currentTop;
|
|
2625
|
+
let currentLeft;
|
|
2626
|
+
const calculatePosition = (position === 'absolute' || position === 'fixed') &&
|
|
2627
|
+
(currentTopString + currentLeftString).includes('auto');
|
|
2628
|
+
if (calculatePosition) {
|
|
2629
|
+
const currentPosition = $element.position();
|
|
2630
|
+
currentTop = currentPosition.top;
|
|
2631
|
+
currentLeft = currentPosition.left;
|
|
2632
|
+
}
|
|
2633
|
+
else {
|
|
2634
|
+
currentTop = parseFloat(currentTopString);
|
|
2635
|
+
currentLeft = parseFloat(currentLeftString);
|
|
2636
|
+
}
|
|
2637
|
+
const computedValue = isFunction(value)
|
|
2638
|
+
? value.call(element, index, extend({}, currentOffset))
|
|
2639
|
+
: value;
|
|
2640
|
+
$element.css({
|
|
2641
|
+
top: computedValue.top != null
|
|
2642
|
+
? computedValue.top - currentOffset.top + currentTop
|
|
2643
|
+
: undefined,
|
|
2644
|
+
left: computedValue.left != null
|
|
2645
|
+
? computedValue.left - currentOffset.left + currentLeft
|
|
2646
|
+
: undefined,
|
|
2647
|
+
});
|
|
2648
|
+
};
|
|
2649
|
+
// eslint-disable-next-line
|
|
2650
|
+
$.fn.offset = function (value) {
|
|
2651
|
+
// 获取坐标
|
|
2652
|
+
if (!arguments.length) {
|
|
2653
|
+
if (!this.length) {
|
|
2654
|
+
return undefined;
|
|
2655
|
+
}
|
|
2656
|
+
return get(this[0]);
|
|
2657
|
+
}
|
|
2658
|
+
// 设置坐标
|
|
2659
|
+
return this.each(function (index) {
|
|
2660
|
+
set(this, value, index);
|
|
2661
|
+
});
|
|
2662
|
+
};
|
|
2663
|
+
|
|
2664
|
+
$.fn.off = function (types,
|
|
2665
|
+
// eslint-disable-next-line
|
|
2666
|
+
selector,
|
|
2667
|
+
// eslint-disable-next-line
|
|
2668
|
+
callback) {
|
|
2669
|
+
// types 是对象
|
|
2670
|
+
if (isObjectLike(types)) {
|
|
2671
|
+
eachObject(types, (type, fn) => {
|
|
2672
|
+
// this.off('click', undefined, function () {})
|
|
2673
|
+
// this.off('click', '.box', function () {})
|
|
2674
|
+
this.off(type, selector, fn);
|
|
2675
|
+
});
|
|
2676
|
+
return this;
|
|
2677
|
+
}
|
|
2678
|
+
// selector 不存在
|
|
2679
|
+
if (selector === false || isFunction(selector)) {
|
|
2680
|
+
callback = selector;
|
|
2681
|
+
selector = undefined;
|
|
2682
|
+
// this.off('click', undefined, function () {})
|
|
2683
|
+
}
|
|
2684
|
+
// callback 传入 `false`,相当于 `return false`
|
|
2685
|
+
if (callback === false) {
|
|
2686
|
+
callback = returnFalse;
|
|
2687
|
+
}
|
|
2688
|
+
return this.each(function () {
|
|
2689
|
+
remove(this, types, callback, selector);
|
|
2690
|
+
});
|
|
2691
|
+
};
|
|
2692
|
+
|
|
2693
|
+
$.fn.on = function (
|
|
2694
|
+
// eslint-disable-next-line
|
|
2695
|
+
types,
|
|
2696
|
+
// eslint-disable-next-line
|
|
2697
|
+
selector,
|
|
2698
|
+
// eslint-disable-next-line
|
|
2699
|
+
data,
|
|
2700
|
+
// eslint-disable-next-line
|
|
2701
|
+
callback, one) {
|
|
2702
|
+
// types 可以是 type/func 对象
|
|
2703
|
+
if (isObjectLike(types)) {
|
|
2704
|
+
// (types-Object, selector, data)
|
|
2705
|
+
if (!isString(selector)) {
|
|
2706
|
+
// (types-Object, data)
|
|
2707
|
+
data = data || selector;
|
|
2708
|
+
selector = undefined;
|
|
2709
|
+
}
|
|
2710
|
+
eachObject(types, (type, fn) => {
|
|
2711
|
+
// selector 和 data 都可能是 undefined
|
|
2712
|
+
// @ts-ignore
|
|
2713
|
+
this.on(type, selector, data, fn, one);
|
|
2714
|
+
});
|
|
2715
|
+
return this;
|
|
2716
|
+
}
|
|
2717
|
+
if (data == null && callback == null) {
|
|
2718
|
+
// (types, fn)
|
|
2719
|
+
callback = selector;
|
|
2720
|
+
data = selector = undefined;
|
|
2721
|
+
}
|
|
2722
|
+
else if (callback == null) {
|
|
2723
|
+
if (isString(selector)) {
|
|
2724
|
+
// (types, selector, fn)
|
|
2725
|
+
callback = data;
|
|
2726
|
+
data = undefined;
|
|
2727
|
+
}
|
|
2728
|
+
else {
|
|
2729
|
+
// (types, data, fn)
|
|
2730
|
+
callback = data;
|
|
2731
|
+
data = selector;
|
|
2732
|
+
selector = undefined;
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
if (callback === false) {
|
|
2736
|
+
callback = returnFalse;
|
|
2737
|
+
}
|
|
2738
|
+
else if (!callback) {
|
|
2739
|
+
return this;
|
|
2740
|
+
}
|
|
2741
|
+
// $().one()
|
|
2742
|
+
if (one) {
|
|
2743
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
2744
|
+
const _this = this;
|
|
2745
|
+
const origCallback = callback;
|
|
2746
|
+
callback = function (event, ...dataN) {
|
|
2747
|
+
_this.off(event.type, selector, callback);
|
|
2748
|
+
return origCallback.call(this, event, ...dataN);
|
|
2749
|
+
};
|
|
2750
|
+
}
|
|
2751
|
+
return this.each(function () {
|
|
2752
|
+
add(this, types, callback, data, selector);
|
|
2753
|
+
});
|
|
2754
|
+
};
|
|
2755
|
+
|
|
2756
|
+
eachArray(['insertBefore', 'insertAfter'], (name, nameIndex) => {
|
|
2757
|
+
// eslint-disable-next-line
|
|
2758
|
+
$.fn[name] = function (target) {
|
|
2759
|
+
const $element = nameIndex ? $(this.get().reverse()) : this; // 顺序和 jQuery 保持一致
|
|
2760
|
+
const $target = $(target);
|
|
2761
|
+
const result = [];
|
|
2762
|
+
$target.each((index, target) => {
|
|
2763
|
+
if (!target.parentNode) {
|
|
2764
|
+
return;
|
|
2765
|
+
}
|
|
2766
|
+
$element.each((_, element) => {
|
|
2767
|
+
const newItem = index
|
|
2768
|
+
? element.cloneNode(true)
|
|
2769
|
+
: element;
|
|
2770
|
+
const existingItem = nameIndex ? target.nextSibling : target;
|
|
2771
|
+
result.push(newItem);
|
|
2772
|
+
target.parentNode.insertBefore(newItem, existingItem);
|
|
2773
|
+
});
|
|
2774
|
+
});
|
|
2775
|
+
return $(nameIndex ? result.reverse() : result);
|
|
2776
|
+
};
|
|
2777
|
+
});
|
|
2778
|
+
|
|
2779
|
+
$.fn.remove = function (selector) {
|
|
2780
|
+
return this.each((_, element) => {
|
|
2781
|
+
if (!selector || $(element).is(selector)) {
|
|
2782
|
+
removeChild(element);
|
|
2783
|
+
}
|
|
2784
|
+
});
|
|
2785
|
+
};
|
|
2786
|
+
|
|
2787
|
+
eachArray(['appendTo', 'prependTo'], (name, nameIndex) => {
|
|
2788
|
+
// eslint-disable-next-line
|
|
2789
|
+
$.fn[name] = function (target) {
|
|
2790
|
+
const extraChilds = [];
|
|
2791
|
+
const $target = $(target).map((_, element) => {
|
|
2792
|
+
const childNodes = element.childNodes;
|
|
2793
|
+
const childLength = childNodes.length;
|
|
2794
|
+
if (childLength) {
|
|
2795
|
+
return childNodes[nameIndex ? 0 : childLength - 1];
|
|
2796
|
+
}
|
|
2797
|
+
const child = createElement('div');
|
|
2798
|
+
appendChild(element, child);
|
|
2799
|
+
extraChilds.push(child);
|
|
2800
|
+
return child;
|
|
2801
|
+
});
|
|
2802
|
+
const $result = this[nameIndex ? 'insertBefore' : 'insertAfter']($target);
|
|
2803
|
+
$(extraChilds).remove();
|
|
2804
|
+
return $result;
|
|
2805
|
+
};
|
|
2806
|
+
});
|
|
2807
|
+
|
|
2808
|
+
const style = i$2 `:host{position:absolute;top:0;left:0;display:block;width:100%;height:100%;overflow:hidden;pointer-events:none}.surface{position:absolute;top:0;left:0;width:100%;height:100%;transition-duration:280ms;transition-property:background-color;pointer-events:none;transition-timing-function:var(--mdui-motion-easing-standard)}.hover{background-color:rgba(var(--mdui-comp-ripple-state-layer-color,var(--mdui-color-on-surface)),var(--mdui-state-layer-hover))}:host-context([focus-visible]) .focused{background-color:rgba(var(--mdui-comp-ripple-state-layer-color,var(--mdui-color-on-surface)),var(--mdui-state-layer-focus))}.dragged{background-color:rgba(var(--mdui-comp-ripple-state-layer-color,var(--mdui-color-on-surface)),var(--mdui-state-layer-dragged))}.wave{position:absolute;z-index:1;background-color:rgb(var(--mdui-comp-ripple-state-layer-color,var(--mdui-color-on-surface)));border-radius:50%;transform:translate3d(0,0,0) scale(.4);opacity:0;animation:225ms ease 0s 1 normal forwards running mdui-comp-ripple-radius-in,75ms ease 0s 1 normal forwards running mdui-comp-ripple-opacity-in;pointer-events:none}.out{transform:translate3d(var(--mdui-comp-ripple-transition-x,0),var(--mdui-comp-ripple-transition-y,0),0) scale(1);animation:150ms ease 0s 1 normal none running mdui-comp-ripple-opacity-out}@keyframes mdui-comp-ripple-radius-in{from{transform:translate3d(0,0,0) scale(.4);animation-timing-function:var(--mdui-motion-easing-standard)}to{transform:translate3d(var(--mdui-comp-ripple-transition-x,0),var(--mdui-comp-ripple-transition-y,0),0) scale(1)}}@keyframes mdui-comp-ripple-opacity-in{from{opacity:0;animation-timing-function:linear}to{opacity:var(--mdui-state-layer-pressed)}}@keyframes mdui-comp-ripple-opacity-out{from{animation-timing-function:linear;opacity:var(--mdui-state-layer-pressed)}to{opacity:0}}`;
|
|
2809
|
+
|
|
2810
|
+
/**
|
|
2811
|
+
* 处理点击时的涟漪动画;及添加 hover、focused、dragged 的背景色
|
|
2812
|
+
* 背景色通过在 .surface 元素上添加对应的 class 实现
|
|
2813
|
+
* 阴影在 ripple-mixin 中处理,通过在 :host 元素上添加 attribute 供 CSS 选择器添加样式
|
|
2814
|
+
*/
|
|
2815
|
+
let Ripple = class Ripple extends MduiElement {
|
|
2816
|
+
constructor() {
|
|
2817
|
+
super(...arguments);
|
|
2818
|
+
/**
|
|
2819
|
+
* 是否禁用涟漪动画
|
|
2820
|
+
*/
|
|
2821
|
+
this.noRipple = false;
|
|
2822
|
+
this.hover = false;
|
|
2823
|
+
this.focused = false;
|
|
2824
|
+
this.dragged = false;
|
|
2825
|
+
this.surfaceRef = ii();
|
|
2826
|
+
}
|
|
2827
|
+
startPress(event) {
|
|
2828
|
+
if (this.noRipple) {
|
|
2829
|
+
return;
|
|
2830
|
+
}
|
|
2831
|
+
const $surface = $(this.surfaceRef.value);
|
|
2832
|
+
const surfaceHeight = $surface.innerHeight();
|
|
2833
|
+
const surfaceWidth = $surface.innerWidth();
|
|
2834
|
+
// 点击位置坐标
|
|
2835
|
+
let touchStartX;
|
|
2836
|
+
let touchStartY;
|
|
2837
|
+
if (!event) {
|
|
2838
|
+
// 未传入事件对象,涟漪从中间扩散
|
|
2839
|
+
touchStartX = surfaceWidth / 2;
|
|
2840
|
+
touchStartY = surfaceHeight / 2;
|
|
2841
|
+
}
|
|
2842
|
+
else {
|
|
2843
|
+
// 传入了事件对象,涟漪从点击位置扩散
|
|
2844
|
+
const touchPosition = typeof TouchEvent !== 'undefined' &&
|
|
2845
|
+
event instanceof TouchEvent &&
|
|
2846
|
+
event.touches.length
|
|
2847
|
+
? event.touches[0]
|
|
2848
|
+
: event;
|
|
2849
|
+
const offset = $surface.offset();
|
|
2850
|
+
// 点击位置不在 surface 内,不执行
|
|
2851
|
+
if (touchPosition.pageX < offset.left ||
|
|
2852
|
+
touchPosition.pageX > offset.left + surfaceWidth ||
|
|
2853
|
+
touchPosition.pageY < offset.top ||
|
|
2854
|
+
touchPosition.pageY > offset.top + surfaceHeight) {
|
|
2855
|
+
return;
|
|
2856
|
+
}
|
|
2857
|
+
touchStartX = touchPosition.pageX - offset.left;
|
|
2858
|
+
touchStartY = touchPosition.pageY - offset.top;
|
|
2859
|
+
}
|
|
2860
|
+
// 涟漪直径
|
|
2861
|
+
const diameter = Math.max(Math.pow(Math.pow(surfaceHeight, 2) + Math.pow(surfaceWidth, 2), 0.5), 48);
|
|
2862
|
+
// 涟漪扩散动画
|
|
2863
|
+
const translateX = `${-touchStartX + surfaceWidth / 2}px`;
|
|
2864
|
+
const translateY = `${-touchStartY + surfaceHeight / 2}px`;
|
|
2865
|
+
const translate = `translate3d(${translateX}, ${translateY}, 0) scale(1)`;
|
|
2866
|
+
// 涟漪 DOM 元素
|
|
2867
|
+
$('<div class="wave"></div>')
|
|
2868
|
+
.css({
|
|
2869
|
+
width: diameter,
|
|
2870
|
+
height: diameter,
|
|
2871
|
+
marginTop: -diameter / 2,
|
|
2872
|
+
marginLeft: -diameter / 2,
|
|
2873
|
+
left: touchStartX,
|
|
2874
|
+
top: touchStartY,
|
|
2875
|
+
})
|
|
2876
|
+
.each((_, wave) => {
|
|
2877
|
+
wave.style.setProperty('--mdui-comp-ripple-transition-x', translateX);
|
|
2878
|
+
wave.style.setProperty('--mdui-comp-ripple-transition-y', translateY);
|
|
2879
|
+
})
|
|
2880
|
+
.prependTo(this.surfaceRef.value)
|
|
2881
|
+
.each((_, wave) => wave.clientLeft) // 重绘
|
|
2882
|
+
.css('transform', translate)
|
|
2883
|
+
.on('animationend', function (e) {
|
|
2884
|
+
const event = e;
|
|
2885
|
+
if (event.animationName === 'mdui-comp-ripple-radius-in') {
|
|
2886
|
+
$(this).data('filled', true); // 扩散动画完成后,添加标记
|
|
2887
|
+
}
|
|
2888
|
+
});
|
|
2889
|
+
}
|
|
2890
|
+
endPress() {
|
|
2891
|
+
const $waves = $(this.surfaceRef.value)
|
|
2892
|
+
.children()
|
|
2893
|
+
.filter((_, wave) => !$(wave).data('removing'))
|
|
2894
|
+
.data('removing', true);
|
|
2895
|
+
const hideAndRemove = ($waves) => {
|
|
2896
|
+
$waves
|
|
2897
|
+
.addClass('out')
|
|
2898
|
+
.each((_, wave) => wave.clientLeft) // 重绘
|
|
2899
|
+
.on('animationend', function () {
|
|
2900
|
+
$(this).remove();
|
|
2901
|
+
});
|
|
2902
|
+
};
|
|
2903
|
+
// 扩散动画未完成,先完成扩散,再隐藏并移除
|
|
2904
|
+
$waves
|
|
2905
|
+
.filter((_, wave) => !$(wave).data('filled'))
|
|
2906
|
+
.on('animationend', function (e) {
|
|
2907
|
+
const event = e;
|
|
2908
|
+
if (event.animationName === 'mdui-comp-ripple-radius-in') {
|
|
2909
|
+
hideAndRemove($(this));
|
|
2910
|
+
}
|
|
2911
|
+
});
|
|
2912
|
+
// 扩散动画已完成,直接隐藏并移除
|
|
2913
|
+
hideAndRemove($waves.filter((_, wave) => !!$(wave).data('filled')));
|
|
2914
|
+
}
|
|
2915
|
+
startHover() {
|
|
2916
|
+
this.hover = true;
|
|
2917
|
+
}
|
|
2918
|
+
endHover() {
|
|
2919
|
+
this.hover = false;
|
|
2920
|
+
}
|
|
2921
|
+
startFocus() {
|
|
2922
|
+
this.focused = true;
|
|
2923
|
+
}
|
|
2924
|
+
endFocus() {
|
|
2925
|
+
this.focused = false;
|
|
2926
|
+
}
|
|
2927
|
+
startDrag() {
|
|
2928
|
+
this.dragged = true;
|
|
2929
|
+
}
|
|
2930
|
+
endDrag() {
|
|
2931
|
+
this.dragged = false;
|
|
2932
|
+
}
|
|
2933
|
+
render() {
|
|
2934
|
+
return ke `<div ${Kt(this.surfaceRef)} class="surface ${Rt({
|
|
2935
|
+
hover: this.hover,
|
|
2936
|
+
focused: this.focused,
|
|
2937
|
+
dragged: this.dragged,
|
|
2938
|
+
})}"></div>`;
|
|
2939
|
+
}
|
|
2940
|
+
};
|
|
2941
|
+
Ripple.styles = [componentStyle, style];
|
|
2942
|
+
__decorate([
|
|
2943
|
+
n({
|
|
2944
|
+
type: Boolean,
|
|
2945
|
+
reflect: true,
|
|
2946
|
+
converter: booleanConverter,
|
|
2947
|
+
attribute: 'no-ripple',
|
|
2948
|
+
})
|
|
2949
|
+
], Ripple.prototype, "noRipple", void 0);
|
|
2950
|
+
__decorate([
|
|
2951
|
+
r()
|
|
2952
|
+
], Ripple.prototype, "hover", void 0);
|
|
2953
|
+
__decorate([
|
|
2954
|
+
r()
|
|
2955
|
+
], Ripple.prototype, "focused", void 0);
|
|
2956
|
+
__decorate([
|
|
2957
|
+
r()
|
|
2958
|
+
], Ripple.prototype, "dragged", void 0);
|
|
2959
|
+
Ripple = __decorate([
|
|
2960
|
+
t$1('mdui-ripple')
|
|
2961
|
+
], Ripple);
|
|
2962
|
+
|
|
2963
|
+
/**
|
|
2964
|
+
* hover, pressed, dragged 三个属性用于添加到 rippleTarget 属性指定的元素上,供 CSS 选择题添加样式
|
|
2965
|
+
*
|
|
2966
|
+
* TODO: dragged 功能
|
|
2967
|
+
*
|
|
2968
|
+
* NOTE:
|
|
2969
|
+
* 不支持触控的屏幕上事件顺序为:pointerdown -> (8ms) -> mousedown -> pointerup -> (1ms) -> mouseup -> (1ms) -> click
|
|
2970
|
+
*
|
|
2971
|
+
* 支持触控的屏幕上事件顺序为:pointerdown -> (8ms) -> touchstart -> pointerup -> (1ms) -> touchend -> (5ms) -> mousedown -> mouseup -> click
|
|
2972
|
+
* pointermove 比较灵敏,有可能触发了 pointermove 但没有触发 touchmove
|
|
2973
|
+
*
|
|
2974
|
+
* 支持触摸笔的屏幕上事件顺序为:todo
|
|
2975
|
+
*/
|
|
2976
|
+
const RippleMixin = (superclass) => {
|
|
2977
|
+
class Mixin extends superclass {
|
|
2978
|
+
constructor() {
|
|
2979
|
+
super(...arguments);
|
|
2980
|
+
/**
|
|
2981
|
+
* 是否禁用涟漪动画
|
|
2982
|
+
*/
|
|
2983
|
+
this.noRipple = false;
|
|
2984
|
+
/**
|
|
2985
|
+
* 当前激活的是第几个 <mdui-ripple>。仅一个组件中有多个 <mdui-ripple> 时可以使用该属性
|
|
2986
|
+
* 若值为 undefined,则组件中所有 <mdui-ripple> 都激活
|
|
2987
|
+
*/
|
|
2988
|
+
this.rippleIndex = undefined;
|
|
2989
|
+
/**
|
|
2990
|
+
* 获取当前激活的是第几个 <mdui-ripple>。仅一个组件中有多个 <mdui-ripple> 时可以使用该属性
|
|
2991
|
+
* 若值为 undefined,则组件中所有 <mdui-ripple> 都激活
|
|
2992
|
+
* 可在子类中手动指定该方法,指定需要激活的 ripple
|
|
2993
|
+
*/
|
|
2994
|
+
this.getRippleIndex = () => this.rippleIndex;
|
|
2995
|
+
}
|
|
2996
|
+
/**
|
|
2997
|
+
* 子类要添加该属性,指向 <mdui-ripple> 元素
|
|
2998
|
+
* 如果一个组件中包含多个 <mdui-ripple> 元素,则这里可以是一个数组或 NodeList
|
|
2999
|
+
*/
|
|
3000
|
+
get rippleElement() {
|
|
3001
|
+
throw new Error('Must implement rippleElement getter!');
|
|
3002
|
+
}
|
|
3003
|
+
/**
|
|
3004
|
+
* 子类要实现该属性,表示是否禁用 ripple
|
|
3005
|
+
* 如果一个组件中包含多个 <mdui-ripple> 元素,则这里可以是一个数组;也可以是单个值,同时控制多个 <mdui-ripple> 元素
|
|
3006
|
+
*/
|
|
3007
|
+
get rippleDisabled() {
|
|
3008
|
+
throw new Error('Must implement rippleDisabled getter!');
|
|
3009
|
+
}
|
|
3010
|
+
/**
|
|
3011
|
+
* 当前 <mdui-ripple> 元素相对于哪个元素存在,即 hover、pressed、dragged 属性要添加到哪个元素上,默认为 :host
|
|
3012
|
+
* 如果需要修改该属性,则子类可以实现该属性
|
|
3013
|
+
* 如果一个组件中包含多个 <mdui-ripple> 元素,则这里可以是一个数组;也可以是单个值,同时控制多个 <mdui-ripple> 元素
|
|
3014
|
+
*/
|
|
3015
|
+
get rippleTarget() {
|
|
3016
|
+
return this;
|
|
3017
|
+
}
|
|
3018
|
+
firstUpdated(changedProperties) {
|
|
3019
|
+
super.firstUpdated(changedProperties);
|
|
3020
|
+
const $rippleTarget = $(this.rippleTarget);
|
|
3021
|
+
// 监听到事件时,是在第几个 <mdui-ripple> 上触发的事件,记录到 this.rippleIndex 中
|
|
3022
|
+
const setRippleIndex = (event) => {
|
|
3023
|
+
if (isArrayLike(this.rippleTarget)) {
|
|
3024
|
+
this.rippleIndex = $rippleTarget.index(event.target);
|
|
3025
|
+
}
|
|
3026
|
+
};
|
|
3027
|
+
const rippleTargetArr = isArrayLike(this.rippleTarget)
|
|
3028
|
+
? this.rippleTarget
|
|
3029
|
+
: [this.rippleTarget];
|
|
3030
|
+
rippleTargetArr.forEach((rippleTarget) => {
|
|
3031
|
+
rippleTarget.addEventListener('pointerdown', (event) => {
|
|
3032
|
+
setRippleIndex(event);
|
|
3033
|
+
this.startPress(event);
|
|
3034
|
+
});
|
|
3035
|
+
rippleTarget.addEventListener('pointerenter', (event) => {
|
|
3036
|
+
setRippleIndex(event);
|
|
3037
|
+
this.startHover(event);
|
|
3038
|
+
});
|
|
3039
|
+
rippleTarget.addEventListener('pointerleave', (event) => {
|
|
3040
|
+
setRippleIndex(event);
|
|
3041
|
+
this.endHover(event);
|
|
3042
|
+
});
|
|
3043
|
+
rippleTarget.addEventListener('focus', (event) => {
|
|
3044
|
+
setRippleIndex(event);
|
|
3045
|
+
this.startFocus();
|
|
3046
|
+
});
|
|
3047
|
+
rippleTarget.addEventListener('blur', (event) => {
|
|
3048
|
+
setRippleIndex(event);
|
|
3049
|
+
this.endFocus();
|
|
3050
|
+
});
|
|
3051
|
+
});
|
|
3052
|
+
}
|
|
3053
|
+
/**
|
|
3054
|
+
* 若存在多个 <mdui-ripple>,但 rippleTarget 为同一个,则 hover 状态无法在多个 <mdui-ripple> 之间切换
|
|
3055
|
+
* 所以把 startHover 和 endHover 设置为 protected,供子类调用
|
|
3056
|
+
* 子类中,在 getRippleIndex() 的返回值变更前调用 endHover(event),变更后调用 startHover(event)
|
|
3057
|
+
*/
|
|
3058
|
+
startHover(event) {
|
|
3059
|
+
if (event.pointerType !== 'mouse' || this.isRippleDisabled()) {
|
|
3060
|
+
return;
|
|
3061
|
+
}
|
|
3062
|
+
this.getRippleTarget().setAttribute('hover', '');
|
|
3063
|
+
this.getRippleElement().startHover();
|
|
3064
|
+
}
|
|
3065
|
+
endHover(event) {
|
|
3066
|
+
if (event.pointerType !== 'mouse' || this.isRippleDisabled()) {
|
|
3067
|
+
return;
|
|
3068
|
+
}
|
|
3069
|
+
this.getRippleTarget().removeAttribute('hover');
|
|
3070
|
+
this.getRippleElement().endHover();
|
|
3071
|
+
}
|
|
3072
|
+
/**
|
|
3073
|
+
* 当前激活的 <mdui-ripple> 元素是否被禁用
|
|
3074
|
+
*/
|
|
3075
|
+
isRippleDisabled() {
|
|
3076
|
+
const disabled = this.rippleDisabled;
|
|
3077
|
+
if (!Array.isArray(disabled)) {
|
|
3078
|
+
return disabled;
|
|
3079
|
+
}
|
|
3080
|
+
const rippleIndex = this.getRippleIndex();
|
|
3081
|
+
if (rippleIndex !== undefined) {
|
|
3082
|
+
return disabled[rippleIndex];
|
|
3083
|
+
}
|
|
3084
|
+
return disabled.length ? disabled[0] : false;
|
|
3085
|
+
}
|
|
3086
|
+
/**
|
|
3087
|
+
* 获取当前激活的 <mdui-ripple> 元素实例
|
|
3088
|
+
*/
|
|
3089
|
+
getRippleElement() {
|
|
3090
|
+
const ripple = this.rippleElement;
|
|
3091
|
+
if (!isArrayLike(ripple)) {
|
|
3092
|
+
return ripple;
|
|
3093
|
+
}
|
|
3094
|
+
const rippleIndex = this.getRippleIndex();
|
|
3095
|
+
if (rippleIndex !== undefined) {
|
|
3096
|
+
return ripple[rippleIndex];
|
|
3097
|
+
}
|
|
3098
|
+
return ripple[0];
|
|
3099
|
+
}
|
|
3100
|
+
/**
|
|
3101
|
+
* 获取当前激活的 <mdui-ripple> 元素相对于哪个元素存在
|
|
3102
|
+
*/
|
|
3103
|
+
getRippleTarget() {
|
|
3104
|
+
const target = this.rippleTarget;
|
|
3105
|
+
if (!isArrayLike(target)) {
|
|
3106
|
+
return target;
|
|
3107
|
+
}
|
|
3108
|
+
const rippleIndex = this.getRippleIndex();
|
|
3109
|
+
if (rippleIndex !== undefined) {
|
|
3110
|
+
return target[rippleIndex];
|
|
3111
|
+
}
|
|
3112
|
+
return target[0];
|
|
3113
|
+
}
|
|
3114
|
+
startFocus() {
|
|
3115
|
+
if (this.isRippleDisabled()) {
|
|
3116
|
+
return;
|
|
3117
|
+
}
|
|
3118
|
+
this.getRippleElement().startFocus();
|
|
3119
|
+
}
|
|
3120
|
+
endFocus() {
|
|
3121
|
+
if (this.isRippleDisabled()) {
|
|
3122
|
+
return;
|
|
3123
|
+
}
|
|
3124
|
+
this.getRippleElement().endFocus();
|
|
3125
|
+
}
|
|
3126
|
+
startPress(event) {
|
|
3127
|
+
// 为鼠标时操作,仅响应鼠标左键点击
|
|
3128
|
+
if (this.isRippleDisabled() || event.button) {
|
|
3129
|
+
return;
|
|
3130
|
+
}
|
|
3131
|
+
const target = this.getRippleTarget();
|
|
3132
|
+
target.setAttribute('pressed', '');
|
|
3133
|
+
// 手指触摸触发涟漪
|
|
3134
|
+
if (['touch', 'pen'].includes(event.pointerType)) {
|
|
3135
|
+
let hidden = false;
|
|
3136
|
+
// 手指触摸后,延迟一段时间触发涟漪,避免手指滑动时也触发涟漪
|
|
3137
|
+
let timer = setTimeout(() => {
|
|
3138
|
+
timer = 0;
|
|
3139
|
+
this.getRippleElement().startPress(event);
|
|
3140
|
+
}, 70);
|
|
3141
|
+
const hideRipple = () => {
|
|
3142
|
+
// 如果手指没有移动,且涟漪动画还没有开始,则开始涟漪动画
|
|
3143
|
+
if (timer) {
|
|
3144
|
+
clearTimeout(timer);
|
|
3145
|
+
timer = 0;
|
|
3146
|
+
this.getRippleElement().startPress(event);
|
|
3147
|
+
}
|
|
3148
|
+
if (!hidden) {
|
|
3149
|
+
hidden = true;
|
|
3150
|
+
this.endPress();
|
|
3151
|
+
}
|
|
3152
|
+
target.removeEventListener('pointerup', hideRipple);
|
|
3153
|
+
target.removeEventListener('pointercancel', hideRipple);
|
|
3154
|
+
};
|
|
3155
|
+
// 手指移动后,移除涟漪动画
|
|
3156
|
+
const touchMove = () => {
|
|
3157
|
+
if (timer) {
|
|
3158
|
+
clearTimeout(timer);
|
|
3159
|
+
timer = 0;
|
|
3160
|
+
}
|
|
3161
|
+
target.removeEventListener('touchmove', touchMove);
|
|
3162
|
+
};
|
|
3163
|
+
// pointermove 事件过于灵敏,可能在未触发 touchmove 的情况下,触发了 pointermove 事件,导致正常的点击操作没有显示涟漪
|
|
3164
|
+
// 因此这里监听 touchmove 事件
|
|
3165
|
+
target.addEventListener('touchmove', touchMove);
|
|
3166
|
+
target.addEventListener('pointerup', hideRipple);
|
|
3167
|
+
target.addEventListener('pointercancel', hideRipple);
|
|
3168
|
+
}
|
|
3169
|
+
// 鼠标点击触发涟漪,点击后立即触发涟漪(仅鼠标左键能触发涟漪)
|
|
3170
|
+
if (event.pointerType === 'mouse' && event.button === 0) {
|
|
3171
|
+
const hideRipple = () => {
|
|
3172
|
+
this.endPress();
|
|
3173
|
+
target.removeEventListener('pointerup', hideRipple);
|
|
3174
|
+
target.removeEventListener('pointercancel', hideRipple);
|
|
3175
|
+
target.removeEventListener('pointerleave', hideRipple);
|
|
3176
|
+
};
|
|
3177
|
+
this.getRippleElement().startPress(event);
|
|
3178
|
+
target.addEventListener('pointerup', hideRipple);
|
|
3179
|
+
target.addEventListener('pointercancel', hideRipple);
|
|
3180
|
+
target.addEventListener('pointerleave', hideRipple);
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
endPress() {
|
|
3184
|
+
if (this.isRippleDisabled()) {
|
|
3185
|
+
return;
|
|
3186
|
+
}
|
|
3187
|
+
this.getRippleTarget().removeAttribute('pressed');
|
|
3188
|
+
this.getRippleElement().endPress();
|
|
3189
|
+
}
|
|
3190
|
+
startDrag() {
|
|
3191
|
+
if (this.isRippleDisabled()) {
|
|
3192
|
+
return;
|
|
3193
|
+
}
|
|
3194
|
+
this.getRippleElement().startDrag();
|
|
3195
|
+
}
|
|
3196
|
+
endDrag() {
|
|
3197
|
+
if (this.isRippleDisabled()) {
|
|
3198
|
+
return;
|
|
3199
|
+
}
|
|
3200
|
+
this.getRippleElement().endDrag();
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3203
|
+
__decorate([
|
|
3204
|
+
n({
|
|
3205
|
+
type: Boolean,
|
|
3206
|
+
reflect: true,
|
|
3207
|
+
converter: booleanConverter,
|
|
3208
|
+
attribute: 'no-ripple',
|
|
3209
|
+
})
|
|
3210
|
+
], Mixin.prototype, "noRipple", void 0);
|
|
3211
|
+
return Mixin;
|
|
3212
|
+
};
|
|
3213
|
+
|
|
3214
|
+
const buttonBaseStyle = i$2 `.button{position:relative;display:inline-flex;align-items:center;justify-content:center;height:100%;padding:0;overflow:hidden;color:inherit;font-size:inherit;font-family:inherit;font-weight:inherit;letter-spacing:inherit;white-space:nowrap;text-align:center;text-decoration:none;vertical-align:middle;background:0 0;border:none;outline:0;cursor:inherit;-webkit-user-select:none;user-select:none;touch-action:manipulation;zoom:1;-webkit-user-drag:none}`;
|
|
3215
|
+
|
|
3216
|
+
class ButtonBase extends AnchorMixin(RippleMixin(FocusableMixin(MduiElement))) {
|
|
3217
|
+
constructor() {
|
|
3218
|
+
super(...arguments);
|
|
3219
|
+
/**
|
|
3220
|
+
* 是否禁用
|
|
3221
|
+
*/
|
|
3222
|
+
this.disabled = false;
|
|
3223
|
+
/**
|
|
3224
|
+
* 是否处于加载中状态
|
|
3225
|
+
*/
|
|
3226
|
+
this.loading = false;
|
|
3227
|
+
/**
|
|
3228
|
+
* 按钮的名称,将与表单数据一起提交。
|
|
3229
|
+
*
|
|
3230
|
+
* **Note**:仅在未设置 `href` 属性时,此属性才有效。
|
|
3231
|
+
*/
|
|
3232
|
+
this.name = '';
|
|
3233
|
+
/**
|
|
3234
|
+
* 按钮的初始值,将与表单数据一起提交。
|
|
3235
|
+
*
|
|
3236
|
+
* **Note**:仅在未设置 `href` 属性时,此属性才有效。
|
|
3237
|
+
*/
|
|
3238
|
+
this.value = '';
|
|
3239
|
+
/**
|
|
3240
|
+
* 按钮的类型。默认类型为 `button`。可选类型包括:
|
|
3241
|
+
*
|
|
3242
|
+
* * `submit`:点击按钮会提交表单数据到服务器
|
|
3243
|
+
* * `reset`:点击按钮会将表单中的所有字段重置为初始值
|
|
3244
|
+
* * `button`:此类型的按钮没有默认行为
|
|
3245
|
+
*
|
|
3246
|
+
* **Note**:仅在未指定 `href` 属性时,此属性才有效。
|
|
3247
|
+
*/
|
|
3248
|
+
this.type = 'button';
|
|
3249
|
+
/**
|
|
3250
|
+
* 如果设置了此属性,表单提交时将不执行表单验证。
|
|
3251
|
+
*
|
|
3252
|
+
* 如果设置了此属性,将覆盖 `<form>` 元素的 `novalidate` 属性。
|
|
3253
|
+
*
|
|
3254
|
+
* **Note**:仅在未设置 `href` 属性且 `type="submit"` 时,此属性才有效。
|
|
3255
|
+
*/
|
|
3256
|
+
this.formNoValidate = false;
|
|
3257
|
+
this.formController = new FormController(this);
|
|
3258
|
+
}
|
|
3259
|
+
/**
|
|
3260
|
+
* 表单验证状态对象,具体参见 [`ValidityState`](https://developer.mozilla.org/zh-CN/docs/Web/API/ValidityState)
|
|
3261
|
+
*/
|
|
3262
|
+
get validity() {
|
|
3263
|
+
if (this.isButton()) {
|
|
3264
|
+
return this.focusElement.validity;
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
/**
|
|
3268
|
+
* 如果表单验证未通过,此属性将包含提示信息。如果验证通过,此属性将为空字符串
|
|
3269
|
+
*/
|
|
3270
|
+
get validationMessage() {
|
|
3271
|
+
if (this.isButton()) {
|
|
3272
|
+
return this.focusElement.validationMessage;
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
get rippleDisabled() {
|
|
3276
|
+
return this.disabled || this.loading;
|
|
3277
|
+
}
|
|
3278
|
+
get focusElement() {
|
|
3279
|
+
return this.isButton()
|
|
3280
|
+
? this.renderRoot?.querySelector('._button')
|
|
3281
|
+
: !this.focusDisabled
|
|
3282
|
+
? this.renderRoot?.querySelector('._a')
|
|
3283
|
+
: this;
|
|
3284
|
+
}
|
|
3285
|
+
get focusDisabled() {
|
|
3286
|
+
return this.disabled || this.loading;
|
|
3287
|
+
}
|
|
3288
|
+
/**
|
|
3289
|
+
* 检查表单字段是否通过验证。如果未通过,返回 `false` 并触发 `invalid` 事件;如果通过,返回 `true`
|
|
3290
|
+
*/
|
|
3291
|
+
checkValidity() {
|
|
3292
|
+
if (this.isButton()) {
|
|
3293
|
+
const valid = this.focusElement.checkValidity();
|
|
3294
|
+
if (!valid) {
|
|
3295
|
+
// @ts-ignore
|
|
3296
|
+
this.emit('invalid', {
|
|
3297
|
+
bubbles: false,
|
|
3298
|
+
cancelable: true,
|
|
3299
|
+
composed: false,
|
|
3300
|
+
});
|
|
3301
|
+
}
|
|
3302
|
+
return valid;
|
|
3303
|
+
}
|
|
3304
|
+
return true;
|
|
3305
|
+
}
|
|
3306
|
+
/**
|
|
3307
|
+
* 检查表单字段是否通过验证。如果未通过,返回 `false` 并触发 `invalid` 事件;如果通过,返回 `true`。
|
|
3308
|
+
*
|
|
3309
|
+
* 如果验证未通过,还会在组件上显示验证失败的提示。
|
|
3310
|
+
*/
|
|
3311
|
+
reportValidity() {
|
|
3312
|
+
if (this.isButton()) {
|
|
3313
|
+
const invalid = !this.focusElement.reportValidity();
|
|
3314
|
+
if (invalid) {
|
|
3315
|
+
// @ts-ignore
|
|
3316
|
+
this.emit('invalid', {
|
|
3317
|
+
bubbles: false,
|
|
3318
|
+
cancelable: true,
|
|
3319
|
+
composed: false,
|
|
3320
|
+
});
|
|
3321
|
+
// todo 考虑是否要支持 preventDefault() 方法,当前 invalid 状态没有样式
|
|
3322
|
+
}
|
|
3323
|
+
return !invalid;
|
|
3324
|
+
}
|
|
3325
|
+
return true;
|
|
3326
|
+
}
|
|
3327
|
+
/**
|
|
3328
|
+
* 设置自定义的错误提示文本。只要这个文本不为空,就表示字段未通过验证
|
|
3329
|
+
*
|
|
3330
|
+
* @param message 自定义的错误提示文本
|
|
3331
|
+
*/
|
|
3332
|
+
setCustomValidity(message) {
|
|
3333
|
+
if (this.isButton()) {
|
|
3334
|
+
this.focusElement.setCustomValidity(message);
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3337
|
+
firstUpdated(_changedProperties) {
|
|
3338
|
+
super.firstUpdated(_changedProperties);
|
|
3339
|
+
this.addEventListener('click', () => {
|
|
3340
|
+
if (this.type === 'submit') {
|
|
3341
|
+
this.formController.submit(this);
|
|
3342
|
+
}
|
|
3343
|
+
if (this.type === 'reset') {
|
|
3344
|
+
this.formController.reset(this);
|
|
3345
|
+
}
|
|
3346
|
+
});
|
|
3347
|
+
}
|
|
3348
|
+
renderLoading() {
|
|
3349
|
+
return this.loading
|
|
3350
|
+
? ke `<mdui-circular-progress part="loading"></mdui-circular-progress>`
|
|
3351
|
+
: nothingTemplate;
|
|
3352
|
+
}
|
|
3353
|
+
renderButton({ id, className, part, content = ke `<slot></slot>`, }) {
|
|
3354
|
+
return ke `<button id="${to(id)}" class="${cc(['_button', className])}" part="${to(part)}" ?disabled="${this.rippleDisabled || this.focusDisabled}">${content}</button>`;
|
|
3355
|
+
}
|
|
3356
|
+
isButton() {
|
|
3357
|
+
return !this.href;
|
|
3358
|
+
}
|
|
3359
|
+
}
|
|
3360
|
+
ButtonBase.styles = [
|
|
3361
|
+
componentStyle,
|
|
3362
|
+
buttonBaseStyle,
|
|
3363
|
+
];
|
|
3364
|
+
__decorate([
|
|
3365
|
+
n({
|
|
3366
|
+
type: Boolean,
|
|
3367
|
+
reflect: true,
|
|
3368
|
+
converter: booleanConverter,
|
|
3369
|
+
})
|
|
3370
|
+
], ButtonBase.prototype, "disabled", void 0);
|
|
3371
|
+
__decorate([
|
|
3372
|
+
n({
|
|
3373
|
+
type: Boolean,
|
|
3374
|
+
reflect: true,
|
|
3375
|
+
converter: booleanConverter,
|
|
3376
|
+
})
|
|
3377
|
+
], ButtonBase.prototype, "loading", void 0);
|
|
3378
|
+
__decorate([
|
|
3379
|
+
n({ reflect: true })
|
|
3380
|
+
], ButtonBase.prototype, "name", void 0);
|
|
3381
|
+
__decorate([
|
|
3382
|
+
n({ reflect: true })
|
|
3383
|
+
], ButtonBase.prototype, "value", void 0);
|
|
3384
|
+
__decorate([
|
|
3385
|
+
n({ reflect: true })
|
|
3386
|
+
], ButtonBase.prototype, "type", void 0);
|
|
3387
|
+
__decorate([
|
|
3388
|
+
n({ reflect: true })
|
|
3389
|
+
], ButtonBase.prototype, "form", void 0);
|
|
3390
|
+
__decorate([
|
|
3391
|
+
n({ reflect: true, attribute: 'formaction' })
|
|
3392
|
+
], ButtonBase.prototype, "formAction", void 0);
|
|
3393
|
+
__decorate([
|
|
3394
|
+
n({ reflect: true, attribute: 'formenctype' })
|
|
3395
|
+
], ButtonBase.prototype, "formEnctype", void 0);
|
|
3396
|
+
__decorate([
|
|
3397
|
+
n({ reflect: true, attribute: 'formmethod' })
|
|
3398
|
+
], ButtonBase.prototype, "formMethod", void 0);
|
|
3399
|
+
__decorate([
|
|
3400
|
+
n({
|
|
3401
|
+
type: Boolean,
|
|
3402
|
+
reflect: true,
|
|
3403
|
+
converter: booleanConverter,
|
|
3404
|
+
attribute: 'formnovalidate',
|
|
3405
|
+
})
|
|
3406
|
+
], ButtonBase.prototype, "formNoValidate", void 0);
|
|
3407
|
+
__decorate([
|
|
3408
|
+
n({ reflect: true, attribute: 'formtarget' })
|
|
3409
|
+
], ButtonBase.prototype, "formTarget", void 0);
|
|
3410
|
+
|
|
3411
|
+
exports.ButtonBase = ButtonBase;
|
|
3412
|
+
exports.HasSlotController = HasSlotController;
|
|
3413
|
+
exports.Kt = Kt;
|
|
3414
|
+
exports.__decorate = __decorate;
|
|
3415
|
+
exports.booleanConverter = booleanConverter;
|
|
3416
|
+
exports.i = i$2;
|
|
3417
|
+
exports.ii = ii;
|
|
3418
|
+
exports.ke = ke;
|
|
3419
|
+
exports.n = n;
|
|
3420
|
+
exports.nothingTemplate = nothingTemplate;
|
|
3421
|
+
exports.t = t$1;
|
|
3422
|
+
|
|
3423
|
+
//# sourceMappingURL=button-base-f4219018.js.map
|