@descope/web-components-ui 1.0.78 → 1.0.79

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. package/dist/index.esm.js +47 -61
  2. package/dist/index.esm.js.map +1 -1
  3. package/dist/umd/878.js +1 -1
  4. package/dist/umd/988.js +1 -0
  5. package/dist/umd/descope-button-index-js.js +1 -1
  6. package/dist/umd/descope-checkbox-index-js.js +1 -1
  7. package/dist/umd/descope-combo-box-index-js.js +1 -1
  8. package/dist/umd/descope-container-index-js.js +1 -1
  9. package/dist/umd/descope-date-picker-index-js.js +1 -1
  10. package/dist/umd/descope-divider-index-js.js +1 -1
  11. package/dist/umd/descope-email-field-index-js.js +1 -1
  12. package/dist/umd/descope-image-index-js.js +1 -1
  13. package/dist/umd/descope-link-index-js.js +1 -1
  14. package/dist/umd/descope-loader-linear-index-js.js +1 -1
  15. package/dist/umd/descope-loader-radial-index-js.js +1 -1
  16. package/dist/umd/descope-logo-index-js.js +1 -1
  17. package/dist/umd/descope-number-field-index-js.js +1 -1
  18. package/dist/umd/descope-passcode-descope-passcode-internal-index-js.js +1 -1
  19. package/dist/umd/descope-passcode-index-js.js +1 -1
  20. package/dist/umd/descope-password-field-index-js.js +1 -1
  21. package/dist/umd/descope-phone-field-descope-phone-field-internal-index-js.js +1 -1
  22. package/dist/umd/descope-phone-field-index-js.js +1 -1
  23. package/dist/umd/descope-switch-toggle-index-js.js +1 -1
  24. package/dist/umd/descope-text-area-index-js.js +1 -1
  25. package/dist/umd/descope-text-field-index-js.js +1 -1
  26. package/dist/umd/descope-text-index-js.js +1 -1
  27. package/dist/umd/index.js +1 -1
  28. package/package.json +1 -1
  29. package/src/baseClasses/createBaseInputClass.js +1 -2
  30. package/src/components/descope-passcode/descope-passcode-internal/PasscodeInternal.js +0 -3
  31. package/src/components/descope-phone-field/descope-phone-field-internal/PhoneFieldInternal.js +0 -3
  32. package/src/mixins/index.js +0 -1
  33. package/src/mixins/inputEventsDispatchingMixin.js +48 -31
  34. package/dist/umd/933.js +0 -1
  35. package/src/mixins/focusMixin.js +0 -23
@@ -1,54 +1,71 @@
1
1
  import { createDispatchEvent } from "../helpers/mixinsHelpers";
2
2
 
3
3
  export const inputEventsDispatchingMixin = (superclass) => class InputEventsDispatchingMixinClass extends superclass {
4
- handleFocusEventsDispatching(focusableElements = []) {
5
- let blurTimerId
6
-
7
- // in order to simulate blur on the input
8
- // we are checking if focus on one of the other elements happened immediately after blur
9
- // if not, the component is no longer focused and we should dispatch blur
10
- focusableElements.forEach(ele => {
11
- ele?.addEventListener('blur', (e) => {
4
+ init() {
5
+ this.#blockNativeEvents();
6
+ this.#handleFocusEventsDispatching();
7
+ this.#handleInputEventDispatching();
8
+
9
+ super.init?.();
10
+ }
11
+
12
+ // we want to block the native (trusted) events and control when these events are being dispatched
13
+ #blockNativeEvents() {
14
+ ['blur', 'focus', 'focusin', 'focusout'].forEach(event => {
15
+ this.addEventListener(event, (e) => {
16
+ e.isTrusted && e.target === this && e.stopImmediatePropagation()
17
+ })
18
+ })
19
+ }
20
+
21
+ #handleFocusEventsDispatching() {
22
+ let timerId
23
+
24
+ // in order to simulate blur & focusout on root input element
25
+ // we are checking if focus on one of the inner elements happened immediately after blur
26
+ // if not, the component is no longer focused and we should dispatch blur & focusout
27
+ this.addEventListener('focusout', (e) => {
28
+ if (e.isTrusted) {
12
29
  e.stopImmediatePropagation();
13
- blurTimerId = setTimeout(() => {
14
- blurTimerId = null
30
+ timerId = setTimeout(() => {
31
+ timerId = null
15
32
  createDispatchEvent.call(this, 'blur');
16
33
  createDispatchEvent.call(this, 'focusout', { bubbles: true });
17
34
  });
18
- })
35
+ }
36
+ })
19
37
 
20
- // in order to simulate focus on the input
21
- // we are holding a blur timer id and clearing it on blur
22
- // if there is a timer id, it means that there was no blur on the input, so it's still focused
23
- // otherwise, it was not focused before, and we need to dispatch a focus event
24
- ele?.addEventListener('focus', (e) => {
38
+ // in order to simulate focus & focusin on the root input element
39
+ // we are holding a timer id and clearing it on focusin
40
+ // if there is a timer id, it means that the root input is still focused
41
+ // otherwise, it was not focused before, and we should dispatch focus & focusin
42
+ this.addEventListener('focusin', (e) => {
43
+ if (e.isTrusted) {
25
44
  e.stopImmediatePropagation();
26
- clearTimeout(blurTimerId)
27
- if (!blurTimerId) {
45
+ clearTimeout(timerId)
46
+ if (!timerId) {
28
47
  createDispatchEvent.call(this, 'focus');
29
48
  createDispatchEvent.call(this, 'focusin', { bubbles: true });
30
49
  }
31
- })
50
+ }
32
51
  })
33
52
  }
34
53
 
35
54
  // we want to block the input events from propagating in case the value of the root input wasn't change
36
55
  // this can happen if we are sanitizing characters on the internal inputs and do not want it to affect the root input element value
37
56
  // in this case, on each input event, we are comparing the root input value to the previous one, and only if it does not match, we are allowing the input event to propagate
38
- handleInputEventDispatching(inputElements) {
57
+ #handleInputEventDispatching() {
39
58
  let previousRootComponentValue = this.value
40
59
 
41
- inputElements.forEach(input => {
42
- input.addEventListener('input', (e) => {
43
- // we are comparing the previous value to the new one,
44
- // and if they have the same value, we are blocking the input event
45
- if (previousRootComponentValue === this.value) {
46
- e.stopImmediatePropagation();
47
- } else {
48
- previousRootComponentValue = this.value
49
- }
50
- });
60
+ this.addEventListener('input', (e) => {
61
+ // we are comparing the previous value to the new one,
62
+ // and if they have the same value, we are blocking the input event
63
+ if (previousRootComponentValue === this.value) {
64
+ e.stopImmediatePropagation();
65
+ } else {
66
+ previousRootComponentValue = this.value
67
+ }
51
68
  });
52
69
 
53
70
  }
54
- }
71
+ }
package/dist/umd/933.js DELETED
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunkDescopeUI=self.webpackChunkDescopeUI||[]).push([[933],{693:(t,e,s)=>{s.d(e,{s:()=>o});var i=s(2061),n=s(357);const r=t=>class extends t{init(){super.init?.(),this.baseElement.addEventListener("mouseover",(t=>{this.setAttribute("hover","true"),t.target.addEventListener("mouseleave",(()=>this.removeAttribute("hover")),{once:!0})}))}};var a=s(8084);const o=({componentName:t,baseSelector:e=""})=>{class s extends HTMLElement{static get componentName(){return t}#t;#e=!0;get baseSelector(){return e}get baseElement(){return this.#t??=this.baseSelector?this.rootElement.querySelector(this.baseSelector):this,this.#t||console.warn("missing base element for component",this.localName),this.#t}get rootElement(){return this.shadowRoot||this}connectedCallback(){super.connectedCallback?.(),this.rootElement.isConnected&&this.#e&&(this.#e=!1,this.init?.())}}return(0,i.qC)(n.A,r,a.Q)(s)}},5279:(t,e,s)=>{s.d(e,{gh:()=>i,k4:()=>n,qM:()=>a,qg:()=>r});const i="descope",n=3,r="host",a="@"},4567:(t,e,s)=>{s.d(e,{Db:()=>d,FX:()=>r,P$:()=>a,Tk:()=>c,iY:()=>h,oP:()=>u,tg:()=>l});var i=s(2061),n=s(5279);const r=(t,e,{excludeAttrs:s=[],includeAttrs:i=[]})=>{const n=Array.from(t.attributes).filter((t=>!s.includes(t.name)&&(!i.length||i.includes(t.name)))).map((t=>t.name));e(n),new MutationObserver((t=>{for(const n of t)"attributes"!==n.type||s.includes(n.attributeName)||i.length&&!i.includes(n.attributeName)||e([n.attributeName])})).observe(t,{attributes:!0})},a=(t,e)=>{e({addedNodes:Array.from(t.children),removedNodes:[]}),new MutationObserver((t=>{for(const s of t)"childList"===s.type&&e(s)})).observe(t,{childList:!0})},o=(t,e,s={})=>i=>{i.forEach((i=>{const n=s[i]||i,r=t.getAttribute(i);null!==r?e.getAttribute(n)!==r&&e.setAttribute(n,r):e.removeAttribute(n)}))},l=(t,e,s)=>{r(t,o(t,e),s),r(e,o(e,t),s)},h=t=>(0,i.E3)(n.gh,t),c=(...t)=>`--${(0,i.E3)(...t)}`,u=(t,e,s={})=>{r(t,o(t,e,s.mapAttrs),s)},d=(t,e,s=[])=>{if(!s.length)return;const i=s.reduce(((t,s)=>Object.assign(t,{[s]:{get:()=>e[s],set(t){e[s]=t}}})),{});Object.defineProperties(t,i)}},2061:(t,e,s)=>{s.d(e,{E3:()=>n,GL:()=>i,mf:()=>a,qC:()=>r});const i=t=>t.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[\s_.]+/g,"-").toLowerCase(),n=(...t)=>i(t.filter((t=>!!t)).join("-")),r=(...t)=>e=>t.reduceRight(((t,e)=>e(t)),e),a=t=>"function"==typeof t},7878:(t,e,s)=>{function i(t,e={}){const s=new Event(t,e);this[`on${t}`]?.(s),this.dispatchEvent(s)}s.d(e,{C:()=>i})},357:(t,e,s)=>{s.d(e,{A:()=>i});const i=t=>class extends t{#s(){const e=this.localName;if(!t.componentName)throw Error('component name is not defined on super class, make sure you have a static get for "componentName"');if(e!==t.componentName)throw Error(`component name mismatch, expected "${t.componentName}", current "${e}"`)}init(){super.init?.(),this.#s()}}},1933:(t,e,s)=>{s.d(e,{li:()=>C,Ae:()=>A.A,DM:()=>p,yk:()=>c,e4:()=>u,pY:()=>S,mE:()=>x,wX:()=>b,QT:()=>T.Q,Iw:()=>M,dj:()=>f,P4:()=>L});var i=s(5279),n=s(2061),r=s(4567),a=s(5561);const o=(t,...e)=>`var(${t}${e.length?` , ${o(...e)}`:""})`;class l{constructor(){this.styleMap=new Map}add(t,e,s){this.styleMap.has(t)||this.styleMap.set(t,[]),this.styleMap.set(t,[...this.styleMap.get(t),{property:e,value:s}])}toString(){return Array.from(this.styleMap.entries()).reduce(((t,[e,s])=>t+`${e} { \n${s.map((({property:t,value:e})=>`${t}: ${e}`)).join(";\n")} \n}\n\n`),"")}}const h=(t,e)=>Object.keys(e).reduce(((e,s)=>Object.assign(e,{[s]:(0,r.Tk)(t,s)})),{}),c=({mappings:t={}})=>e=>class extends e{static get cssVarList(){return{...e.cssVarList,...h(e.componentName,{...t})}}#i;#n;#r;#a;#o;#l;#h;#c;constructor({getRootElement:e,componentNameSuffix:s="",themeSection:r=i.qg,baseSelector:a}={}){super(),this.#a=s,this.#o=r,this.#l=e?.(this)||this.shadowRoot,this.#h=a??this.baseSelector,this.#c=Object.keys(t).map((t=>(0,n.E3)("st",s,t)))}get componentTheme(){return a.componentsThemeManager.currentTheme?.[e.componentName]||""}#u(){this.#n.innerHTML=this.componentTheme[this.#o]}#d(){this.#n=document.createElement("style"),this.#n.id="style-mixin-theme",this.#l.prepend(this.#n),this.#r=a.componentsThemeManager.onCurrentThemeChange(this.#u.bind(this)),this.#u()}#m(){this.#i=document.createElement("style"),this.#i.id="style-mixin-overrides";const t=(s=e.componentName,n=i.k4,Array(n).fill(`.${s}`).join(""));var s,n;this.#i.innerText=`:host(${t}) {}`,this.#l.append(this.#i)}#p(t,s){const i=this.#i?.sheet?.cssRules[0].style;if(!i)return;const n=(0,r.Tk)(e.componentName,t.replace(new RegExp("^st-"),""));s?i?.setProperty(n,s):i?.removeProperty(n)}#g(t=[]){for(const e of t)this.#c.includes(e)&&this.#p(e,this.getAttribute(e));this.#i.innerHTML=this.#i?.sheet?.cssRules[0].cssText}#b(){const s=document.createElement("style");s.id="style-mixin-mappings",s.innerHTML=((t,e,s)=>{const i=new l;return Object.keys(s).forEach((a=>{const l=((t,e)=>{const s={selector:"",property:(0,n.GL)(t)};return e&&Object.keys(e).length?Array.isArray(e)?e.map((t=>Object.assign({},s,t))):[Object.assign({},s,e)]:[s]})(a,s[a]),h=(0,r.Tk)(t,a);l.forEach((({selector:t,property:s})=>{i.add(((t="",e="")=>(0,n.mf)(e)?e(t):`${t}${/^[A-Za-z]/.test(e)?` ${e}`:e}`)(e,t),(0,n.mf)(s)?s():s,o(h))}))})),i.toString()})((0,n.E3)(e.componentName,this.#a),this.#h,t),this.#l.prepend(s)}#E(t){(this.#l.classList||this.#l.host.classList).add(t)}init(){super.init?.(),this.shadowRoot.isConnected&&(this.#E(e.componentName),this.#b(),this.#d(),this.#m(),(0,r.FX)(this,this.#g.bind(this),{}))}disconnectedCallback(){super.disconnectedCallback?.(),this.#r?.()}},u=t=>class extends t{#y=null;static get observedAttributes(){return[...t.observedAttributes||[],"draggable"]}constructor(){super(),this.#y=document.createElement("style"),this.#y.innerText="* { cursor: inherit!important }"}#v(t){t?this.shadowRoot.appendChild(this.#y):this.#y.remove()}attributeChangedCallback(t,e,s){super.attributeChangedCallback?.(t,e,s),"draggable"===t&&this.#v("true"===s)}};var d=s(693),m=s(7878);const p=({componentName:t,wrappedEleName:e,slots:s=[],style:i,excludeAttrsSync:a=[],includeAttrsSync:o=[],includeForwardProps:l=[]})=>{class h extends((0,d.s)({componentName:t,baseSelector:e})){#f=m.C.bind(this,"blur");#A=m.C.bind(this,"focus");constructor(){super().attachShadow({mode:"open"}).innerHTML=`\n\t\t\t<style id="create-proxy">${(0,n.mf)(i)?i():i}</style>\n\t\t\t<${e}>\n\t\t\t<slot></slot>\n\t\t\t${s.map((t=>`<slot name="${t}" slot="${t}"></slot>`)).join("")}\n\t\t\t</${e}>\n\t\t`}focus=()=>this.baseElement.focus();init(){super.init?.(),this.baseElement.addEventListener("blur",(t=>{this.#f()})),this.baseElement.addEventListener("focus",(t=>{this.#A()})),this.addEventListener("focus",(t=>{t.isTrusted&&this.focus()})),(0,r.Db)(this,this.baseElement,l),this.baseElement.onkeydown=t=>{t.shiftKey&&9===t.keyCode&&this.getRootNode()===document&&(this.removeAttribute("tabindex"),setTimeout((()=>this.setAttribute("tabindex","0")),0))},(0,r.tg)(this.baseElement,this,{excludeAttrs:a,includeAttrs:o})}}return h},g=["required","pattern"],b=t=>class extends t{static get observedAttributes(){return[...t.observedAttributes||[],...g]}static get formAssociated(){return!0}#S;constructor(){super(),this.#S=this.attachInternals()}get defaultErrorMsgValueMissing(){return"Please fill out this field."}get defaultErrorMsgPatternMismatch(){return"Please match the requested format."}get defaultErrorMsgTooShort(){return`Minimum length is ${this.getAttribute("minlength")}.`}get defaultErrorMsgTooLong(){return`Maximum length is ${this.getAttribute("maxlength")}. `}getErrorMessage(t){switch(!0){case t.valueMissing:return this.getAttribute("data-errormessage-value-missing")||this.defaultErrorMsgValueMissing;case t.patternMismatch||t.typeMismatch:return this.getAttribute("data-errormessage-pattern-mismatch")||this.defaultErrorMsgPatternMismatch;case t.tooShort:return this.getAttribute("data-errormessage-pattern-mismatch-too-short")||this.defaultErrorMsgTooShort;case t.tooLong:return this.getAttribute("data-errormessage-pattern-mismatch-too-long")||this.defaultErrorMsgTooLong;case t.customError:return this.validationMessage;default:return""}}#M(){const t=this.getValidity();this.#S.setValidity(t,this.getErrorMessage(t))}get validationMessage(){return this.#S.validationMessage}getValidity(){console.warn("getValidity","is not implemented")}checkValidity(){return this.#S.validity.valid}reportValidity(){return this.#S.reportValidity()}get validity(){return this.#S.validity}setCustomValidity(t){t?this.#S.setValidity({customError:!0},t):(this.#S.setValidity({}),this.#M())}get isRequired(){return this.hasAttribute("required")&&"false"!==this.getAttribute("required")}get pattern(){return this.getAttribute("pattern")}get form(){return this.#S.form}attributeChangedCallback(t,e,s){super.attributeChangedCallback?.(t,e,s),g.includes(t)&&this.#M()}init(){super.init?.(),this.addEventListener("change",this.#M),this.addEventListener("invalid",(t=>t.stopPropagation())),this.addEventListener("input",this.#M),setTimeout((()=>this.#M()))}},E=["invalid","required"],y=(t,e,s)=>{Object.defineProperty(t,s,{set:function(t){return e[s]=t},get:function(){return e[s]},configurable:!0})},v=t=>{if(!t)return;let e=t;for(let t=0;t<10;t++)if(e=e.assignedElements()[0],"slot"!==e.localName)return e},f=t=>class extends(b(t)){static get observedAttributes(){return[...t.observedAttributes||[],...E]}#C;#T=m.C.bind(this,"change");constructor(){super(),this.#C=super.inputElement}get inputElement(){const t=this.baseElement.shadowRoot.querySelector('slot[name="input"]'),e=this.baseElement.shadowRoot.querySelector('slot[name="textarea"]');if(this.#C??=v(t)||v(e),!this.#C)throw Error("no input was found");return this.#C}set inputElement(t){this.#C=t}getValidity(){return this.inputElement.validity}reportValidityOnInternalInput(){setTimeout((()=>{this.inputElement.focus(),this.inputElement.reportValidity()}))}reportValidity(){this.checkValidity()||(this.setAttribute("invalid","true"),this.reportValidityOnInternalInput())}handleInternalInputErrorMessage(){this.inputElement.checkValidity()||this.inputElement.setCustomValidity(this.validationMessage)}#L(){this.handleInternalInputErrorMessage(),this.setAttribute("error-message",this.validationMessage)}init(){super.init?.(),this.inputElement.addEventListener("input",(t=>{this.inputElement.checkValidity()||(this.inputElement.setCustomValidity(""),this.setCustomValidity(""),this.baseElement.__onInput(t),this.#L())})),this.baseElement.addEventListener("change",(()=>{this.#T()})),this.addEventListener("blur",(()=>{this.checkValidity()||(this.setAttribute("invalid","true"),this.#L())})),this.addEventListener("focus",(t=>{t.relatedTarget?.form&&t.relatedTarget?.form===this.form&&"BUTTON"===t.relatedTarget?.nodeName&&(this.checkValidity()||this.setAttribute("invalid","true"),this.hasAttribute("invalid")&&this.reportValidityOnInternalInput())})),this.addEventListener("invalid",this.#L),this.handleInternalInputErrorMessage(),this.hasAttribute("tabindex")||this.getRootNode()!==document||this.setAttribute("tabindex",0),y(this,this.inputElement,"value"),y(this,this.inputElement,"selectionStart"),this.setSelectionRange=this.inputElement.setSelectionRange?.bind(this.inputElement)}};var A=s(357);const S=t=>class extends t{init(){super.init?.(),this.addEventListener("blur",(t=>{t.isTrusted&&t.stopImmediatePropagation()})),this.addEventListener("focus",(t=>{t.isTrusted&&t.stopImmediatePropagation()})),this.addEventListener("focusout",(t=>{t.isTrusted&&t.stopImmediatePropagation()})),this.addEventListener("focusin",(t=>{t.isTrusted&&t.stopImmediatePropagation()}))}},M=({name:t,selector:e,mappings:s={},forward:{attributes:a=[],include:o=!0}={}})=>l=>{const u=t||(t=>t.replace(/[^\w\s]/gi,""))(e),d=c({mappings:s})(l);return class extends d{static get cssVarList(){return{...d.cssVarList,[u]:h((0,n.E3)(l.componentName,"_"+u),s)}}#x;constructor(){const t=t=>{const s=t.shadowRoot.querySelector(t.baseSelector),i=e?s.shadowRoot.querySelector(e):s;return i.shadowRoot||i};var s;super({getRootElement:t,componentNameSuffix:"_"+u,themeSection:i.qM+u,baseSelector:":host"}),this.#x=(s=t(this)).host||s}#V(){this.#x.onmouseenter=t=>{t.target.setAttribute("hover","true")},this.#x.onmouseleave=t=>{t.target.removeAttribute("hover")}}init(){super.init?.(),(0,r.oP)(this,this.#x,{[o?"includeAttrs":"excludeAttrs"]:a}),this.#V()}}},C=t=>class extends t{#T=m.C.bind(this,"change");init(){super.init?.(),this.prevValue=this.value,this.addEventListener("change",(t=>{t.stopPropagation()})),this.addEventListener("blur",(()=>{this.value!==this.prevValue&&(this.#T(),this.prevValue=this.value)}))}};var T=s(8084);const L=t=>class extends t{get isReadOnly(){return this.hasAttribute("readonly")&&"false"!==this.getAttribute("readonly")}init(){["focus","blur"].forEach((t=>{this.addEventListener(t,(t=>{this.isReadOnly&&(t.stopImmediatePropagation(),t.preventDefault())}),!0)})),super.init?.()}},x=t=>class extends t{handleFocusEventsDispatching(t=[]){let e;t.forEach((t=>{t?.addEventListener("blur",(t=>{t.stopImmediatePropagation(),e=setTimeout((()=>{e=null,m.C.call(this,"blur"),m.C.call(this,"focusout",{bubbles:!0})}))})),t?.addEventListener("focus",(t=>{t.stopImmediatePropagation(),clearTimeout(e),e||(m.C.call(this,"focus"),m.C.call(this,"focusin",{bubbles:!0}))}))}))}handleInputEventDispatching(t){let e=this.value;t.forEach((t=>{t.addEventListener("input",(t=>{e===this.value?t.stopImmediatePropagation():e=this.value}))}))}}},8084:(t,e,s)=>{s.d(e,{Q:()=>n});var i=s(4567);const n=t=>class extends t{init(){super.init?.(),(0,i.FX)(this,(t=>t.forEach((t=>{const e=this.getAttribute(t);""===e?this.setAttribute(t,"true"):"false"===e&&this.removeAttribute(t)}))),{})}}}}]);
@@ -1,23 +0,0 @@
1
- export const focusMixin = (superclass) => class FocusMixinClass extends superclass {
2
- // we want to block all native events,
3
- // so the input can control when to dispatch it based on its internal behavior
4
- init() {
5
- super.init?.();
6
-
7
- this.addEventListener('blur', (e) => {
8
- e.isTrusted && e.stopImmediatePropagation()
9
- })
10
-
11
- this.addEventListener('focus', (e) => {
12
- e.isTrusted && e.stopImmediatePropagation();
13
- })
14
-
15
- this.addEventListener('focusout', (e) => {
16
- e.isTrusted && e.stopImmediatePropagation();
17
- })
18
-
19
- this.addEventListener('focusin', (e) => {
20
- e.isTrusted && e.stopImmediatePropagation();
21
- })
22
- }
23
- }