@oslokommune/punkt-elements 19.20.0 → 20.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -0
- package/dist/{alert-UbQzzkXb.js → alert-CA1fDbyc.js} +2 -2
- package/dist/{alert-KxCE28nq.cjs → alert-DkyTTo7S.cjs} +1 -1
- package/dist/{backlink-bbYpIZJI.js → backlink-CDBRcaAu.js} +1 -1
- package/dist/{backlink-CqRcFURx.cjs → backlink-CXOxMeyt.cjs} +1 -1
- package/dist/{breadcrumbs-D7gddV5F.js → breadcrumbs-5oUaCef3.js} +1 -1
- package/dist/{breadcrumbs-C_JR4ZI_.cjs → breadcrumbs-zfUto2U5.cjs} +1 -1
- package/dist/{button-BJ6QLwxJ.js → button-Bswo1C0M.js} +1 -1
- package/dist/{button-pFlrTF2P.cjs → button-bVWAX98x.cjs} +1 -1
- package/dist/{calendar-CYsQEfZn.js → calendar-BOd-9PDd.js} +1 -1
- package/dist/{calendar-Fk5ubNGR.cjs → calendar-CDTCgTJn.cjs} +1 -1
- package/dist/{card-CKu696QC.js → card-DH1kPnyi.js} +40 -38
- package/dist/card-njWrvrHm.cjs +67 -0
- package/dist/{checkbox-BLmQSdWB.js → checkbox-DIJbuqWm.js} +1 -1
- package/dist/{checkbox-group-DFKzbaHC.js → checkbox-group-DLLbWgQb.js} +2 -2
- package/dist/{checkbox-group-B9TtWVpG.cjs → checkbox-group-Kua6HuRE.cjs} +1 -1
- package/dist/{checkbox-PAtsn1TO.cjs → checkbox-iMOdzpJ_.cjs} +1 -1
- package/dist/{combobox-CJAmzQFD.cjs → combobox-BwAxmoG9.cjs} +1 -1
- package/dist/{combobox-KnYdXXRm.js → combobox-H5FLG8BV.js} +3 -3
- package/dist/components/card/card.d.ts +0 -10
- package/dist/components/card/index.d.ts +2 -2
- package/dist/components/link/link.d.ts +1 -1
- package/dist/components/linkcard/linkcard.d.ts +0 -1
- package/dist/components/tabs/tabitem.d.ts +2 -1
- package/dist/components/tag/tag.d.ts +4 -2
- package/dist/{consent-BjWx64Gv.cjs → consent-UkinU27V.cjs} +1 -1
- package/dist/{consent-CeJKY2EB.js → consent-p-0n2b9x.js} +1 -1
- package/dist/{datepicker-IMxHS-ex.cjs → datepicker-COar3rRT.cjs} +1 -1
- package/dist/{datepicker-Cco0rRLa.js → datepicker-ZSwWg8xW.js} +4 -4
- package/dist/{fileupload-CjqIhSJ1.cjs → fileupload-DXJtAagE.cjs} +1 -1
- package/dist/{fileupload-BrSWPUcy.js → fileupload-vPDmtXiM.js} +4 -4
- package/dist/{footer-BJCxJUW9.cjs → footer-CpE05IW2.cjs} +1 -1
- package/dist/{footer-DQq09VjI.js → footer-D8t0PCPC.js} +2 -2
- package/dist/{header-C_BUBeOQ.js → header-Bo8uvddg.js} +6 -6
- package/dist/{header-_KjqW2oJ.cjs → header-DzYKgl-k.cjs} +1 -1
- package/dist/{header-menu-BV0XlRez.js → header-menu-BrjsNjBH.js} +1 -1
- package/dist/{header-menu-BiW5cNun.cjs → header-menu-Dq9lwNr1.cjs} +1 -1
- package/dist/{helptext-CL1vxEaL.js → helptext-BFQzrOw4.js} +1 -1
- package/dist/{helptext-B4h3Xlqa.cjs → helptext-Bse1LpRd.cjs} +1 -1
- package/dist/icon-5A378_yh.cjs +1 -0
- package/dist/{icon-C82IxnSO.js → icon-C1oCGwEe.js} +1 -1
- package/dist/{input-wrapper-BNu6kOOn.cjs → input-wrapper-C_Rzwxx7.cjs} +2 -2
- package/dist/{input-wrapper-DowJHbGF.js → input-wrapper-DkpJS1hR.js} +4 -4
- package/dist/{link-DqPFlWxz.cjs → link-B7t4iOKk.cjs} +3 -3
- package/dist/{link-D9kjggXZ.js → link-DZgG_8Ni.js} +12 -7
- package/dist/linkcard-DIG6VYpl.cjs +15 -0
- package/dist/{linkcard-BEmG-2lN.js → linkcard-Dr-r8jBO.js} +22 -18
- package/dist/{loader-lDVe6rUf.js → loader-CFidlqSG.js} +1 -1
- package/dist/{loader-C4fbS8vr.cjs → loader-DTIrOtTo.cjs} +1 -1
- package/dist/messagebox-BLYx3AL7.cjs +16 -0
- package/dist/{messagebox-C8dsqW20.js → messagebox-B_07P0QA.js} +22 -13
- package/dist/{modal-EgQREcb8.cjs → modal-BvTfLfFq.cjs} +1 -1
- package/dist/{modal-D389hSbe.js → modal-CA_M2Ix6.js} +1 -1
- package/dist/{option-group-element-DhYJmGgW.cjs → option-group-element-CVNaBIlP.cjs} +1 -1
- package/dist/{option-group-element-CB0Qqev_.js → option-group-element-DzM8YznZ.js} +1 -1
- package/dist/pkt-alert.cjs +1 -1
- package/dist/pkt-alert.js +1 -1
- package/dist/pkt-backlink.cjs +1 -1
- package/dist/pkt-backlink.js +1 -1
- package/dist/pkt-breadcrumbs.cjs +1 -1
- package/dist/pkt-breadcrumbs.js +1 -1
- package/dist/pkt-button.cjs +1 -1
- package/dist/pkt-button.js +1 -1
- package/dist/pkt-calendar.cjs +1 -1
- package/dist/pkt-calendar.js +1 -1
- package/dist/pkt-card.cjs +1 -1
- package/dist/pkt-card.js +1 -1
- package/dist/pkt-checkbox-group.cjs +1 -1
- package/dist/pkt-checkbox-group.js +1 -1
- package/dist/pkt-checkbox.cjs +1 -1
- package/dist/pkt-checkbox.js +1 -1
- package/dist/pkt-combobox.cjs +1 -1
- package/dist/pkt-combobox.js +1 -1
- package/dist/pkt-consent.cjs +1 -1
- package/dist/pkt-consent.js +1 -1
- package/dist/pkt-datepicker.cjs +1 -1
- package/dist/pkt-datepicker.js +1 -1
- package/dist/pkt-fileupload.cjs +1 -1
- package/dist/pkt-fileupload.js +1 -1
- package/dist/pkt-footer.cjs +1 -1
- package/dist/pkt-footer.js +1 -1
- package/dist/pkt-header-menu.cjs +1 -1
- package/dist/pkt-header-menu.js +1 -1
- package/dist/pkt-header.cjs +1 -1
- package/dist/pkt-header.js +1 -1
- package/dist/pkt-helptext.cjs +1 -1
- package/dist/pkt-helptext.js +1 -1
- package/dist/pkt-icon.cjs +1 -1
- package/dist/pkt-icon.js +1 -1
- package/dist/pkt-index.cjs +1 -1
- package/dist/pkt-index.js +35 -35
- package/dist/pkt-input-wrapper.cjs +1 -1
- package/dist/pkt-input-wrapper.js +1 -1
- package/dist/pkt-link.cjs +1 -1
- package/dist/pkt-link.js +1 -1
- package/dist/pkt-linkcard.cjs +1 -1
- package/dist/pkt-linkcard.js +1 -1
- package/dist/pkt-loader.cjs +1 -1
- package/dist/pkt-loader.js +1 -1
- package/dist/pkt-messagebox.cjs +1 -1
- package/dist/pkt-messagebox.js +1 -1
- package/dist/pkt-modal.cjs +1 -1
- package/dist/pkt-modal.js +1 -1
- package/dist/pkt-radio-group.cjs +1 -1
- package/dist/pkt-radio-group.js +1 -1
- package/dist/pkt-radiobutton.cjs +1 -1
- package/dist/pkt-radiobutton.js +1 -1
- package/dist/pkt-searchinput.cjs +1 -1
- package/dist/pkt-searchinput.js +1 -1
- package/dist/pkt-select.cjs +1 -1
- package/dist/pkt-select.js +1 -1
- package/dist/pkt-tabs.cjs +1 -1
- package/dist/pkt-tabs.js +1 -1
- package/dist/pkt-tag.cjs +1 -1
- package/dist/pkt-tag.js +1 -1
- package/dist/pkt-textarea.cjs +1 -1
- package/dist/pkt-textarea.js +1 -1
- package/dist/pkt-textinput.cjs +1 -1
- package/dist/pkt-textinput.js +1 -1
- package/dist/pkt-timepicker.cjs +1 -1
- package/dist/pkt-timepicker.js +1 -1
- package/dist/{radio-group-CSs8YnEO.js → radio-group-BRY_74od.js} +2 -2
- package/dist/{radio-group-DRNGFfUh.cjs → radio-group-CsUgnEv0.cjs} +1 -1
- package/dist/{radiobutton-Be66H6On.cjs → radiobutton-CQhuG2lj.cjs} +1 -1
- package/dist/{radiobutton-BN67oAvC.js → radiobutton-lHnq8wX_.js} +1 -1
- package/dist/{searchinput-B26-Xp00.js → searchinput-BLGaXkP6.js} +1 -1
- package/dist/{searchinput-Trn6uU2J.cjs → searchinput-TAqMUJ0B.cjs} +1 -1
- package/dist/{select-DZftfjQt.js → select-BvtUxW0Q.js} +1 -1
- package/dist/{select-o6iuy9hC.cjs → select-Dle67Uwv.cjs} +1 -1
- package/dist/shared-types/card.d.ts +5 -17
- package/dist/shared-types/combobox.d.ts +3 -3
- package/dist/shared-types/icon.d.ts +2 -2
- package/dist/shared-types/index.d.ts +9 -8
- package/dist/shared-types/linkcard.d.ts +7 -4
- package/dist/shared-types/messagebox.d.ts +4 -2
- package/dist/shared-types/skin.d.ts +8 -2
- package/dist/{tabs-Bu9PP33-.js → tabs-Bu_-WfCK.js} +1 -1
- package/dist/{tabs-gRjrFqeG.cjs → tabs-Dwk5PKzP.cjs} +1 -1
- package/dist/tag-1SSexs0H.cjs +27 -0
- package/dist/{tag-CtdOrK18.js → tag-CkZ2Mn4a.js} +29 -7
- package/dist/{textarea-Cc2aQLbm.cjs → textarea-DSX3jMlI.cjs} +1 -1
- package/dist/{textarea-DP7GVL2c.js → textarea-Djp5L2Zd.js} +2 -2
- package/dist/{textinput-Dhwotaxv.js → textinput-CBrOZcvL.js} +2 -2
- package/dist/{textinput-B6FPNOJB.cjs → textinput-CN2F3Q3H.cjs} +1 -1
- package/dist/{timepicker-DxwQ7-Bl.js → timepicker-CT4wfrgQ.js} +2 -2
- package/dist/{timepicker-Ce9hXP0B.cjs → timepicker-CkaJkIGn.cjs} +1 -1
- package/package.json +3 -3
- package/src/components/card/card.test.ts +50 -53
- package/src/components/card/card.ts +14 -24
- package/src/components/card/index.ts +2 -2
- package/src/components/checkbox/checkbox.test.ts +3 -3
- package/src/components/checkbox/checkbox.ts +1 -1
- package/src/components/input-wrapper/input-wrapper.ts +1 -1
- package/src/components/link/link.test.ts +14 -18
- package/src/components/link/link.ts +2 -3
- package/src/components/linkcard/linkcard.test.ts +18 -6
- package/src/components/linkcard/linkcard.ts +5 -7
- package/src/components/messagebox/messagebox.test.ts +14 -1
- package/src/components/messagebox/messagebox.ts +13 -2
- package/src/components/radiobutton/radiobutton.test.ts +1 -1
- package/src/components/radiobutton/radiobutton.ts +1 -1
- package/src/components/tabs/tabitem.ts +6 -2
- package/src/components/tag/tag.test.ts +21 -12
- package/src/components/tag/tag.ts +12 -3
- package/dist/card-Da0JkVcv.cjs +0 -64
- package/dist/icon-B3YGHHa7.cjs +0 -1
- package/dist/linkcard-BMJvjo7R.cjs +0 -14
- package/dist/messagebox-DFaDuvHQ.cjs +0 -13
- package/dist/tag-BgHEzLM3.cjs +0 -27
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const e=require("./element-CEarCnHH.cjs"),t=require("./class-map-C82GtM1w.cjs"),n=require("./format-B8meU8Tm.cjs"),r=require("./element-with-slot-CeKuRE3_.cjs");require("./icon-B3YGHHa7.cjs");const i=require("./input-wrapper-BNu6kOOn.cjs"),a=require("./if-defined-Ci4ZQsgL.cjs"),o=require("./ref-B6p6mQkO.cjs"),s=require("./input-element-2LHxo0em.cjs");var c=e=>/^\d{2}:\d{2}$/.test(e)&&parseInt(e.slice(0,2),10)<=23&&parseInt(e.slice(3),10)<=59,l=e=>{let[t,n]=e.split(`:`).map(Number);return t*60+n},u=e=>e?Math.max(1,Math.round(e/60)):1,d=(e,t)=>{let n=e?parseInt(String(e).split(`:`)[0],10):0,r=t?parseInt(String(t).split(`:`)[0],10):23;return Array.from({length:r-n+1},(e,t)=>t+n)},f=e=>{let t=u(e);return Array.from({length:Math.floor(60/t)},(e,n)=>n*t)},p=(e,t,n,r)=>{let i=e===``?n===1?0:23:parseInt(e,10),a=t===``?n===1?0:Math.floor(59/r)*r:parseInt(t,10);return a+=n*r,a>59?(a=0,i=(i+1)%24):a<0&&(a=Math.floor(59/r)*r,i=(i-1+24)%24),{hours:String(i).padStart(2,`0`),minutes:String(a).padStart(2,`0`)}},m=class extends s.t{constructor(...e){super(...e),this.hiddenInputRef=o.t(),this.hoursInputRef=o.t(),this.minutesInputRef=o.t(),this.buttonRef=o.t(),this.value=``,this.hidePicker=!1,this.stepArrows=!1,this._hours=``,this._minutes=``,this._isOpen=!1,this._hoursDigitCount=0,this._hoursFirstDigit=-1,this._minutesDigitCount=0,this._minutesFirstDigit=-1,this._hasFocus=!1,this._outsideClickHandler=e=>{this.contains(e.target)||this._closePopup()},this._handleComponentFocusIn=()=>{this._hasFocus||(this._hasFocus=!0,this.onFocus())},this._handleComponentFocusOut=e=>{this.contains(e.relatedTarget)||(this._hasFocus=!1,this.onBlur())},this._handleHoursKeydown=e=>{let t=e.target;switch(e.key){case`ArrowUp`:{e.preventDefault();let t=this._hours===``?0:parseInt(this._hours,10);this._hours=String((t+1)%24).padStart(2,`0`),this._syncValueFromDisplay(),this.onInput();break}case`ArrowDown`:{e.preventDefault();let t=this._hours===``?0:parseInt(this._hours,10);this._hours=String((t-1+24)%24).padStart(2,`0`),this._syncValueFromDisplay(),this.onInput();break}case`ArrowRight`:e.preventDefault(),this.minutesInputRef.value?.focus();break;case`Backspace`:case`Delete`:this._hoursDigitCount=0,this._hoursFirstDigit=-1;break;case`Tab`:break;case`Enter`:{e.preventDefault();let n=this.internals.form;n?n.requestSubmit():t.blur();break}default:if(/^\d$/.test(e.key)){e.preventDefault();let t=parseInt(e.key,10);if(this._hoursDigitCount===0)this._hoursFirstDigit=t,this._hours=String(t).padStart(2,`0`),this._hoursDigitCount=1,this.onInput(),t>=3&&(this._hoursFirstDigit=-1,this._hoursDigitCount=0,this._syncValueFromDisplay(),this.minutesInputRef.value?.focus());else{let e=this._hoursFirstDigit*10+t;this._hours=e<=23?String(e).padStart(2,`0`):String(t).padStart(2,`0`),this._hoursFirstDigit=-1,this._hoursDigitCount=0,this._syncValueFromDisplay(),this.onInput(),this.minutesInputRef.value?.focus()}}else e.preventDefault()}},this._handleHoursBlur=()=>{this._hours!==``&&(this._hours=String(parseInt(this._hours,10)).padStart(2,`0`)),this._hoursDigitCount=0,this._hoursFirstDigit=-1,this._syncValueFromDisplay()},this._handleMinutesKeydown=e=>{let t=e.target;switch(e.key){case`ArrowUp`:{e.preventDefault();let t=this._minutes===``?0:parseInt(this._minutes,10);this._minutes=String((t+this._minuteStep)%60).padStart(2,`0`),this._syncValueFromDisplay(),this.onInput();break}case`ArrowDown`:{e.preventDefault();let t=this._minutes===``?0:parseInt(this._minutes,10);this._minutes=String((t-this._minuteStep+60)%60).padStart(2,`0`),this._syncValueFromDisplay(),this.onInput();break}case`ArrowLeft`:e.preventDefault(),this.hoursInputRef.value?.focus();break;case`Backspace`:case`Delete`:this._minutesDigitCount=0,this._minutesFirstDigit=-1;break;case`Tab`:break;case`Enter`:{e.preventDefault();let n=this.internals.form;n?n.requestSubmit():t.blur();break}default:if(/^\d$/.test(e.key)){e.preventDefault();let t=parseInt(e.key,10);if(this._minutesDigitCount===0)this._minutesFirstDigit=t,this._minutes=String(t).padStart(2,`0`),this._minutesDigitCount=1,this.onInput(),t>=6&&(this._minutesFirstDigit=-1,this._minutesDigitCount=0,this._syncValueFromDisplay());else{let e=this._minutesFirstDigit*10+t;this._minutes=e<=59?String(e).padStart(2,`0`):String(t).padStart(2,`0`),this._minutesFirstDigit=-1,this._minutesDigitCount=0,this._syncValueFromDisplay(),this.onInput()}}else e.preventDefault()}},this._handleMinutesBlur=()=>{this._minutes!==``&&(this._minutes=String(parseInt(this._minutes,10)).padStart(2,`0`)),this._minutesDigitCount=0,this._minutesFirstDigit=-1,this._syncValueFromDisplay()},this._handlePopupKeydown=e=>{let t=document.activeElement,n=t.closest(`.pkt-timepicker-popup__col`);if(!n)return;let r=Array.from(n.querySelectorAll(`.pkt-timepicker-popup__option`)),i=r.indexOf(t),a=t.dataset.type??``;switch(e.key){case`ArrowDown`:e.preventDefault(),this._focusOptionAndSync(r[Math.min(i+1,r.length-1)],a);break;case`ArrowUp`:e.preventDefault(),this._focusOptionAndSync(r[Math.max(i-1,0)],a);break;case`Home`:e.preventDefault(),this._focusOptionAndSync(r[0],a);break;case`End`:e.preventDefault(),this._focusOptionAndSync(r[r.length-1],a);break;case`ArrowRight`:e.preventDefault(),a===`hour`&&(this._focusOptionAndSync(t,a),this.updateComplete.then(()=>{this._scrollToSelected(),this._focusSelectedOrFirst(`minute`)}));break;case`ArrowLeft`:e.preventDefault(),a===`minute`&&(this._focusOptionAndSync(t,a),this.updateComplete.then(()=>{this._scrollToSelected(),this._focusSelectedOrFirst(`hour`)}));break;case`Enter`:case` `:e.preventDefault(),t.click();break;case`Escape`:e.preventDefault(),this._closePopup(),this.buttonRef.value?.focus()}}}get inputRef(){return this.hiddenInputRef}manageValidity(e){let t=this.hoursInputRef.value;if(!t)return;let r=this.pktStrings.get(`validation`);if(this.required&&!this.value){this.internals.setValidity({valueMissing:!0},r.valueMissing,t),this._setAriaInvalid(!0);return}if(!this.value){this.internals.setValidity({}),this._setAriaInvalid(!1);return}let i=l(this.value),a=u(this.step);if(this.min&&i<l(String(this.min)))this.internals.setValidity({rangeUnderflow:!0},n.t(r.rangeUnderflowMin,{min:String(this.min)}),t),this._setAriaInvalid(!0);else if(this.max&&i>l(String(this.max)))this.internals.setValidity({rangeOverflow:!0},n.t(r.rangeOverflowMax,{max:String(this.max)}),t),this._setAriaInvalid(!0);else if(this.step&&i%a!==0){let e=a===60?r.timeStepMismatchHour:a===30?r.timeStepMismatchHalfHour:n.t(r.timeStepMismatch,{step:`${a}, ${a*2}, ${a*3}`});this.internals.setValidity({stepMismatch:!0},e,t),this._setAriaInvalid(!0)}else this.internals.setValidity({}),this._setAriaInvalid(!1)}_describedBy(){return i.r({id:`${this.id}-hours`,hasHelptext:!!this.helptext||this.hasSlotContent(`helptext`),ariaDescribedby:this.ariaDescribedby})}_setAriaInvalid(e){if(!this.touched&&e)return;let t=this.hoursInputRef.value,n=this.minutesInputRef.value;if(e)t?.setAttribute(`aria-invalid`,`true`),n?.setAttribute(`aria-invalid`,`true`);else{if(this.hasError)return;t?.removeAttribute(`aria-invalid`),n?.removeAttribute(`aria-invalid`)}}connectedCallback(){super.connectedCallback(),this.addEventListener(`focusin`,this._handleComponentFocusIn),this.addEventListener(`focusout`,this._handleComponentFocusOut),document.addEventListener(`click`,this._outsideClickHandler)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener(`focusin`,this._handleComponentFocusIn),this.removeEventListener(`focusout`,this._handleComponentFocusOut),document.removeEventListener(`click`,this._outsideClickHandler)}willUpdate(e){super.willUpdate(e),e.has(`value`)&&this._syncDisplayFromValue()}updated(e){super.updated(e),this.classList.add(`pkt-timepicker`),this.classList.toggle(`pkt-timepicker--stepper`,this.stepArrows),this.classList.toggle(`pkt-timepicker--fullwidth`,this.fullwidth),this.classList.toggle(`pkt-timepicker--medium`,this.inputSize===`medium`),this.classList.toggle(`pkt-timepicker--small`,this.inputSize===`small`),this.classList.toggle(`pkt-timepicker--xsmall`,this.inputSize===`xsmall`),e.has(`step`)&&this.step!==null&&!this._isValidStep(this.step)&&console.warn(`pkt-timepicker: step="${this.step}" er ikke en gyldig verdi. Step må være et multiplum av 60 (hele minutter) eller nøyaktig 3600 (hel time).`)}formResetCallback(){super.formResetCallback(),this._hours=``,this._minutes=``,this._isOpen=!1}_isValidStep(e){return e===3600||e<3600&&3600%e==0&&e%60==0}_syncDisplayFromValue(){let e=c(this.value)?this.value.split(`:`):null;e?(this._hours=e[0],this._minutes=e[1]):(this._hours=``,this._minutes=``)}_syncValueFromDisplay(){if(this._hours!==``&&this._minutes!==``){let e=`${this._hours}:${this._minutes}`;e!==this.value&&(this.value=e,this.onChange(e))}else this.value!==``&&(this.value=``,this.onChange(``))}get _minuteStep(){return u(this.step)}get _hourOptions(){return d(this.min,this.max)}get _minuteOptions(){return f(this.step)}_openPopup(){this._isOpen=!0,this.updateComplete.then(()=>{this._scrollToSelected(),this._focusSelectedOrFirst(`hour`)})}_closePopup(){this._isOpen=!1,this._syncValueFromDisplay()}_togglePopup(){this._isOpen?this._closePopup():this._openPopup()}_scrollToSelected(){let e=this.querySelector(`.pkt-timepicker-popup`);e&&e.querySelectorAll(`.pkt-timepicker-popup__col`).forEach(e=>{let t=e.querySelector(`.pkt-timepicker-popup__option--selected`);t&&t.scrollIntoView({block:`center`})})}_focusSelectedOrFirst(e){let t=this.querySelector(`.pkt-timepicker-popup`);if(!t)return;let n=t.querySelectorAll(`.pkt-timepicker-popup__col`),r=e===`hour`?n[0]:n[1];if(!r)return;let i=r.querySelector(`.pkt-timepicker-popup__option--selected`),a=r.querySelector(`.pkt-timepicker-popup__option`);(i||a)?.focus()}_handleOptionClick(e,t){let n=String(e).padStart(2,`0`);t===`hour`?(this._hours=n,this.updateComplete.then(()=>this._focusSelectedOrFirst(`minute`))):(this._minutes=n,this._closePopup(),this.buttonRef.value?.focus())}_focusOptionAndSync(e,t){if(!e)return;let n=parseInt(e.dataset.value??`0`,10);t===`hour`?this._hours=String(n).padStart(2,`0`):this._minutes=String(n).padStart(2,`0`),e.focus()}_stepTime(e){let t=p(this._hours,this._minutes,e,this._minuteStep);this._hours=t.hours,this._minutes=t.minutes,this._syncValueFromDisplay()}_renderOption(n,r){let i=String(n).padStart(2,`0`),a=n===(r===`hour`?this._hours===``?NaN:parseInt(this._hours,10):this._minutes===``?NaN:parseInt(this._minutes,10));return e._`
|
|
1
|
+
const e=require("./element-CEarCnHH.cjs"),t=require("./class-map-C82GtM1w.cjs"),n=require("./format-B8meU8Tm.cjs"),r=require("./element-with-slot-CeKuRE3_.cjs");require("./icon-5A378_yh.cjs");const i=require("./input-wrapper-C_Rzwxx7.cjs"),a=require("./if-defined-Ci4ZQsgL.cjs"),o=require("./ref-B6p6mQkO.cjs"),s=require("./input-element-2LHxo0em.cjs");var c=e=>/^\d{2}:\d{2}$/.test(e)&&parseInt(e.slice(0,2),10)<=23&&parseInt(e.slice(3),10)<=59,l=e=>{let[t,n]=e.split(`:`).map(Number);return t*60+n},u=e=>e?Math.max(1,Math.round(e/60)):1,d=(e,t)=>{let n=e?parseInt(String(e).split(`:`)[0],10):0,r=t?parseInt(String(t).split(`:`)[0],10):23;return Array.from({length:r-n+1},(e,t)=>t+n)},f=e=>{let t=u(e);return Array.from({length:Math.floor(60/t)},(e,n)=>n*t)},p=(e,t,n,r)=>{let i=e===``?n===1?0:23:parseInt(e,10),a=t===``?n===1?0:Math.floor(59/r)*r:parseInt(t,10);return a+=n*r,a>59?(a=0,i=(i+1)%24):a<0&&(a=Math.floor(59/r)*r,i=(i-1+24)%24),{hours:String(i).padStart(2,`0`),minutes:String(a).padStart(2,`0`)}},m=class extends s.t{constructor(...e){super(...e),this.hiddenInputRef=o.t(),this.hoursInputRef=o.t(),this.minutesInputRef=o.t(),this.buttonRef=o.t(),this.value=``,this.hidePicker=!1,this.stepArrows=!1,this._hours=``,this._minutes=``,this._isOpen=!1,this._hoursDigitCount=0,this._hoursFirstDigit=-1,this._minutesDigitCount=0,this._minutesFirstDigit=-1,this._hasFocus=!1,this._outsideClickHandler=e=>{this.contains(e.target)||this._closePopup()},this._handleComponentFocusIn=()=>{this._hasFocus||(this._hasFocus=!0,this.onFocus())},this._handleComponentFocusOut=e=>{this.contains(e.relatedTarget)||(this._hasFocus=!1,this.onBlur())},this._handleHoursKeydown=e=>{let t=e.target;switch(e.key){case`ArrowUp`:{e.preventDefault();let t=this._hours===``?0:parseInt(this._hours,10);this._hours=String((t+1)%24).padStart(2,`0`),this._syncValueFromDisplay(),this.onInput();break}case`ArrowDown`:{e.preventDefault();let t=this._hours===``?0:parseInt(this._hours,10);this._hours=String((t-1+24)%24).padStart(2,`0`),this._syncValueFromDisplay(),this.onInput();break}case`ArrowRight`:e.preventDefault(),this.minutesInputRef.value?.focus();break;case`Backspace`:case`Delete`:this._hoursDigitCount=0,this._hoursFirstDigit=-1;break;case`Tab`:break;case`Enter`:{e.preventDefault();let n=this.internals.form;n?n.requestSubmit():t.blur();break}default:if(/^\d$/.test(e.key)){e.preventDefault();let t=parseInt(e.key,10);if(this._hoursDigitCount===0)this._hoursFirstDigit=t,this._hours=String(t).padStart(2,`0`),this._hoursDigitCount=1,this.onInput(),t>=3&&(this._hoursFirstDigit=-1,this._hoursDigitCount=0,this._syncValueFromDisplay(),this.minutesInputRef.value?.focus());else{let e=this._hoursFirstDigit*10+t;this._hours=e<=23?String(e).padStart(2,`0`):String(t).padStart(2,`0`),this._hoursFirstDigit=-1,this._hoursDigitCount=0,this._syncValueFromDisplay(),this.onInput(),this.minutesInputRef.value?.focus()}}else e.preventDefault()}},this._handleHoursBlur=()=>{this._hours!==``&&(this._hours=String(parseInt(this._hours,10)).padStart(2,`0`)),this._hoursDigitCount=0,this._hoursFirstDigit=-1,this._syncValueFromDisplay()},this._handleMinutesKeydown=e=>{let t=e.target;switch(e.key){case`ArrowUp`:{e.preventDefault();let t=this._minutes===``?0:parseInt(this._minutes,10);this._minutes=String((t+this._minuteStep)%60).padStart(2,`0`),this._syncValueFromDisplay(),this.onInput();break}case`ArrowDown`:{e.preventDefault();let t=this._minutes===``?0:parseInt(this._minutes,10);this._minutes=String((t-this._minuteStep+60)%60).padStart(2,`0`),this._syncValueFromDisplay(),this.onInput();break}case`ArrowLeft`:e.preventDefault(),this.hoursInputRef.value?.focus();break;case`Backspace`:case`Delete`:this._minutesDigitCount=0,this._minutesFirstDigit=-1;break;case`Tab`:break;case`Enter`:{e.preventDefault();let n=this.internals.form;n?n.requestSubmit():t.blur();break}default:if(/^\d$/.test(e.key)){e.preventDefault();let t=parseInt(e.key,10);if(this._minutesDigitCount===0)this._minutesFirstDigit=t,this._minutes=String(t).padStart(2,`0`),this._minutesDigitCount=1,this.onInput(),t>=6&&(this._minutesFirstDigit=-1,this._minutesDigitCount=0,this._syncValueFromDisplay());else{let e=this._minutesFirstDigit*10+t;this._minutes=e<=59?String(e).padStart(2,`0`):String(t).padStart(2,`0`),this._minutesFirstDigit=-1,this._minutesDigitCount=0,this._syncValueFromDisplay(),this.onInput()}}else e.preventDefault()}},this._handleMinutesBlur=()=>{this._minutes!==``&&(this._minutes=String(parseInt(this._minutes,10)).padStart(2,`0`)),this._minutesDigitCount=0,this._minutesFirstDigit=-1,this._syncValueFromDisplay()},this._handlePopupKeydown=e=>{let t=document.activeElement,n=t.closest(`.pkt-timepicker-popup__col`);if(!n)return;let r=Array.from(n.querySelectorAll(`.pkt-timepicker-popup__option`)),i=r.indexOf(t),a=t.dataset.type??``;switch(e.key){case`ArrowDown`:e.preventDefault(),this._focusOptionAndSync(r[Math.min(i+1,r.length-1)],a);break;case`ArrowUp`:e.preventDefault(),this._focusOptionAndSync(r[Math.max(i-1,0)],a);break;case`Home`:e.preventDefault(),this._focusOptionAndSync(r[0],a);break;case`End`:e.preventDefault(),this._focusOptionAndSync(r[r.length-1],a);break;case`ArrowRight`:e.preventDefault(),a===`hour`&&(this._focusOptionAndSync(t,a),this.updateComplete.then(()=>{this._scrollToSelected(),this._focusSelectedOrFirst(`minute`)}));break;case`ArrowLeft`:e.preventDefault(),a===`minute`&&(this._focusOptionAndSync(t,a),this.updateComplete.then(()=>{this._scrollToSelected(),this._focusSelectedOrFirst(`hour`)}));break;case`Enter`:case` `:e.preventDefault(),t.click();break;case`Escape`:e.preventDefault(),this._closePopup(),this.buttonRef.value?.focus()}}}get inputRef(){return this.hiddenInputRef}manageValidity(e){let t=this.hoursInputRef.value;if(!t)return;let r=this.pktStrings.get(`validation`);if(this.required&&!this.value){this.internals.setValidity({valueMissing:!0},r.valueMissing,t),this._setAriaInvalid(!0);return}if(!this.value){this.internals.setValidity({}),this._setAriaInvalid(!1);return}let i=l(this.value),a=u(this.step);if(this.min&&i<l(String(this.min)))this.internals.setValidity({rangeUnderflow:!0},n.t(r.rangeUnderflowMin,{min:String(this.min)}),t),this._setAriaInvalid(!0);else if(this.max&&i>l(String(this.max)))this.internals.setValidity({rangeOverflow:!0},n.t(r.rangeOverflowMax,{max:String(this.max)}),t),this._setAriaInvalid(!0);else if(this.step&&i%a!==0){let e=a===60?r.timeStepMismatchHour:a===30?r.timeStepMismatchHalfHour:n.t(r.timeStepMismatch,{step:`${a}, ${a*2}, ${a*3}`});this.internals.setValidity({stepMismatch:!0},e,t),this._setAriaInvalid(!0)}else this.internals.setValidity({}),this._setAriaInvalid(!1)}_describedBy(){return i.r({id:`${this.id}-hours`,hasHelptext:!!this.helptext||this.hasSlotContent(`helptext`),ariaDescribedby:this.ariaDescribedby})}_setAriaInvalid(e){if(!this.touched&&e)return;let t=this.hoursInputRef.value,n=this.minutesInputRef.value;if(e)t?.setAttribute(`aria-invalid`,`true`),n?.setAttribute(`aria-invalid`,`true`);else{if(this.hasError)return;t?.removeAttribute(`aria-invalid`),n?.removeAttribute(`aria-invalid`)}}connectedCallback(){super.connectedCallback(),this.addEventListener(`focusin`,this._handleComponentFocusIn),this.addEventListener(`focusout`,this._handleComponentFocusOut),document.addEventListener(`click`,this._outsideClickHandler)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener(`focusin`,this._handleComponentFocusIn),this.removeEventListener(`focusout`,this._handleComponentFocusOut),document.removeEventListener(`click`,this._outsideClickHandler)}willUpdate(e){super.willUpdate(e),e.has(`value`)&&this._syncDisplayFromValue()}updated(e){super.updated(e),this.classList.add(`pkt-timepicker`),this.classList.toggle(`pkt-timepicker--stepper`,this.stepArrows),this.classList.toggle(`pkt-timepicker--fullwidth`,this.fullwidth),this.classList.toggle(`pkt-timepicker--medium`,this.inputSize===`medium`),this.classList.toggle(`pkt-timepicker--small`,this.inputSize===`small`),this.classList.toggle(`pkt-timepicker--xsmall`,this.inputSize===`xsmall`),e.has(`step`)&&this.step!==null&&!this._isValidStep(this.step)&&console.warn(`pkt-timepicker: step="${this.step}" er ikke en gyldig verdi. Step må være et multiplum av 60 (hele minutter) eller nøyaktig 3600 (hel time).`)}formResetCallback(){super.formResetCallback(),this._hours=``,this._minutes=``,this._isOpen=!1}_isValidStep(e){return e===3600||e<3600&&3600%e==0&&e%60==0}_syncDisplayFromValue(){let e=c(this.value)?this.value.split(`:`):null;e?(this._hours=e[0],this._minutes=e[1]):(this._hours=``,this._minutes=``)}_syncValueFromDisplay(){if(this._hours!==``&&this._minutes!==``){let e=`${this._hours}:${this._minutes}`;e!==this.value&&(this.value=e,this.onChange(e))}else this.value!==``&&(this.value=``,this.onChange(``))}get _minuteStep(){return u(this.step)}get _hourOptions(){return d(this.min,this.max)}get _minuteOptions(){return f(this.step)}_openPopup(){this._isOpen=!0,this.updateComplete.then(()=>{this._scrollToSelected(),this._focusSelectedOrFirst(`hour`)})}_closePopup(){this._isOpen=!1,this._syncValueFromDisplay()}_togglePopup(){this._isOpen?this._closePopup():this._openPopup()}_scrollToSelected(){let e=this.querySelector(`.pkt-timepicker-popup`);e&&e.querySelectorAll(`.pkt-timepicker-popup__col`).forEach(e=>{let t=e.querySelector(`.pkt-timepicker-popup__option--selected`);t&&t.scrollIntoView({block:`center`})})}_focusSelectedOrFirst(e){let t=this.querySelector(`.pkt-timepicker-popup`);if(!t)return;let n=t.querySelectorAll(`.pkt-timepicker-popup__col`),r=e===`hour`?n[0]:n[1];if(!r)return;let i=r.querySelector(`.pkt-timepicker-popup__option--selected`),a=r.querySelector(`.pkt-timepicker-popup__option`);(i||a)?.focus()}_handleOptionClick(e,t){let n=String(e).padStart(2,`0`);t===`hour`?(this._hours=n,this.updateComplete.then(()=>this._focusSelectedOrFirst(`minute`))):(this._minutes=n,this._closePopup(),this.buttonRef.value?.focus())}_focusOptionAndSync(e,t){if(!e)return;let n=parseInt(e.dataset.value??`0`,10);t===`hour`?this._hours=String(n).padStart(2,`0`):this._minutes=String(n).padStart(2,`0`),e.focus()}_stepTime(e){let t=p(this._hours,this._minutes,e,this._minuteStep);this._hours=t.hours,this._minutes=t.minutes,this._syncValueFromDisplay()}_renderOption(n,r){let i=String(n).padStart(2,`0`),a=n===(r===`hour`?this._hours===``?NaN:parseInt(this._hours,10):this._minutes===``?NaN:parseInt(this._minutes,10));return e._`
|
|
2
2
|
<button
|
|
3
3
|
class=${t.t({"pkt-btn":!0,"pkt-btn--tertiary":!0,"pkt-btn--small":!0,"pkt-btn--label-only":!0,"pkt-timepicker-popup__option":!0,"pkt-timepicker-popup__option--selected":a})}
|
|
4
4
|
type="button"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oslokommune/punkt-elements",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "20.0.0",
|
|
4
4
|
"description": "Komponentbiblioteket til Punkt, designsystem for Oslo kommune",
|
|
5
5
|
"homepage": "https://punkt.oslo.kommune.no",
|
|
6
6
|
"author": "Team Designsystem, Oslo kommune",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@lit-labs/router": "^0.1.4",
|
|
38
|
-
"@oslokommune/punkt-assets": "^
|
|
38
|
+
"@oslokommune/punkt-assets": "^20.0.0",
|
|
39
39
|
"@testing-library/dom": "^10.4.2",
|
|
40
40
|
"@testing-library/jest-dom": "^7.0.1",
|
|
41
41
|
"@types/jest-axe": "^3.5.9",
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
"engines": {
|
|
79
79
|
"node": "^22.19.0 || ^24.0.0 || ^26.0.0"
|
|
80
80
|
},
|
|
81
|
-
"gitHead": "
|
|
81
|
+
"gitHead": "8a73041756098b52bdb8e9f6448bb1a96184e3c9"
|
|
82
82
|
}
|
|
@@ -10,8 +10,6 @@ expect.extend(toHaveNoViolations)
|
|
|
10
10
|
export interface CardTestConfig extends BaseTestConfig {
|
|
11
11
|
skin?: string
|
|
12
12
|
layout?: string
|
|
13
|
-
padding?: string
|
|
14
|
-
borderOnHover?: boolean
|
|
15
13
|
heading?: string
|
|
16
14
|
subheading?: string
|
|
17
15
|
headingLevel?: number
|
|
@@ -99,24 +97,21 @@ describe('PktCard', () => {
|
|
|
99
97
|
const { card } = await createCardTest()
|
|
100
98
|
await card.updateComplete
|
|
101
99
|
|
|
102
|
-
expect(card.skin).toBe('
|
|
100
|
+
expect(card.skin).toBe('gray')
|
|
103
101
|
expect(card.layout).toBe('vertical')
|
|
104
|
-
expect(card.padding).toBe('default')
|
|
105
|
-
expect(card.borderOnHover).toBe(true)
|
|
106
102
|
expect(card.tagPosition).toBe('top')
|
|
107
|
-
expect(card.imageShape).toBe('square')
|
|
108
103
|
expect(card.openLinkInNewTab).toBe(false)
|
|
109
104
|
expect(card.headingLevel).toBe(3)
|
|
110
105
|
|
|
111
106
|
const article = card.querySelector('article')
|
|
112
|
-
expect(article).toHaveClass('pkt-card--
|
|
107
|
+
expect(article).toHaveClass('pkt-card--gray')
|
|
113
108
|
expect(article).toHaveClass('pkt-card--vertical')
|
|
114
|
-
expect(article).toHaveClass('pkt-card--
|
|
115
|
-
expect(article).
|
|
109
|
+
expect(article).not.toHaveClass('pkt-card--clickable')
|
|
110
|
+
expect(article).not.toHaveAttribute('data-mode')
|
|
116
111
|
})
|
|
117
112
|
|
|
118
113
|
test('applies different skin properties correctly', async () => {
|
|
119
|
-
const skins = ['
|
|
114
|
+
const skins = ['gray', 'outlined', 'transparent', 'white', 'blue', 'green', 'beige']
|
|
120
115
|
|
|
121
116
|
for (const skin of skins) {
|
|
122
117
|
const { card } = await createCardTest({ skin })
|
|
@@ -130,8 +125,24 @@ describe('PktCard', () => {
|
|
|
130
125
|
}
|
|
131
126
|
})
|
|
132
127
|
|
|
128
|
+
test('keeps light-only skins in light mode', async () => {
|
|
129
|
+
for (const skin of ['white', 'blue', 'green', 'beige']) {
|
|
130
|
+
const { card } = await createCardTest({ skin })
|
|
131
|
+
await card.updateComplete
|
|
132
|
+
|
|
133
|
+
expect(card.querySelector('article')).toHaveAttribute('data-mode', 'light')
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
for (const skin of ['gray', 'outlined', 'transparent']) {
|
|
137
|
+
const { card } = await createCardTest({ skin })
|
|
138
|
+
await card.updateComplete
|
|
139
|
+
|
|
140
|
+
expect(card.querySelector('article')).not.toHaveAttribute('data-mode')
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
|
|
133
144
|
test('rejects unsupported skin values and falls back to default', async () => {
|
|
134
|
-
const unsupportedSkins = ['zebra', 'goldenrod', '
|
|
145
|
+
const unsupportedSkins = ['zebra', 'goldenrod', 'outlined-beige', 'rainbow', 'invalid']
|
|
135
146
|
|
|
136
147
|
for (const invalidSkin of unsupportedSkins) {
|
|
137
148
|
const { card } = await createCardTest({ skin: invalidSkin })
|
|
@@ -139,13 +150,13 @@ describe('PktCard', () => {
|
|
|
139
150
|
|
|
140
151
|
// The component should now validate skin values and fall back to default
|
|
141
152
|
expect(card.skin).not.toBe(invalidSkin)
|
|
142
|
-
expect(card.skin).toBe('
|
|
153
|
+
expect(card.skin).toBe('gray') // Should fall back to default
|
|
143
154
|
|
|
144
155
|
const article = card.querySelector('article')
|
|
145
156
|
// Should not have the invalid CSS class
|
|
146
157
|
expect(article).not.toHaveClass(`pkt-card--${invalidSkin}`)
|
|
147
158
|
// Should have the default skin class instead
|
|
148
|
-
expect(article).toHaveClass('pkt-card--
|
|
159
|
+
expect(article).toHaveClass('pkt-card--gray')
|
|
149
160
|
}
|
|
150
161
|
})
|
|
151
162
|
|
|
@@ -159,11 +170,11 @@ describe('PktCard', () => {
|
|
|
159
170
|
|
|
160
171
|
// Should have logged a warning with the correct default value from spec
|
|
161
172
|
expect(localConsoleSpy).toHaveBeenCalledWith(
|
|
162
|
-
'Invalid skin value "zebra". Using default skin "
|
|
173
|
+
'Invalid skin value "zebra". Using default skin "gray".',
|
|
163
174
|
)
|
|
164
175
|
|
|
165
176
|
// Should fall back to default from spec
|
|
166
|
-
expect(card.skin).toBe('
|
|
177
|
+
expect(card.skin).toBe('gray')
|
|
167
178
|
|
|
168
179
|
// Restore and recreate global spy for subsequent tests
|
|
169
180
|
localConsoleSpy.mockRestore()
|
|
@@ -185,32 +196,6 @@ describe('PktCard', () => {
|
|
|
185
196
|
}
|
|
186
197
|
})
|
|
187
198
|
|
|
188
|
-
test('applies different padding properties correctly', async () => {
|
|
189
|
-
const paddingOptions = ['none', 'default']
|
|
190
|
-
|
|
191
|
-
for (const padding of paddingOptions) {
|
|
192
|
-
const { card } = await createCardTest({ padding })
|
|
193
|
-
await card.updateComplete
|
|
194
|
-
|
|
195
|
-
expect(card.padding).toBe(padding)
|
|
196
|
-
expect(card.getAttribute('padding')).toBe(padding)
|
|
197
|
-
|
|
198
|
-
const article = card.querySelector('article')
|
|
199
|
-
expect(article).toHaveClass(`pkt-card--padding-${padding}`)
|
|
200
|
-
}
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
test('handles borderOnHover property correctly', async () => {
|
|
204
|
-
// Test with borderOnHover false
|
|
205
|
-
const { card } = await createCardTest()
|
|
206
|
-
card.borderOnHover = false
|
|
207
|
-
await card.updateComplete
|
|
208
|
-
|
|
209
|
-
expect(card.borderOnHover).toBe(false)
|
|
210
|
-
|
|
211
|
-
const article = card.querySelector('article')
|
|
212
|
-
expect(article).not.toHaveClass('pkt-card--border-on-hover')
|
|
213
|
-
})
|
|
214
199
|
})
|
|
215
200
|
|
|
216
201
|
describe('Heading functionality', () => {
|
|
@@ -288,6 +273,18 @@ describe('PktCard', () => {
|
|
|
288
273
|
|
|
289
274
|
const article = card.querySelector('article')
|
|
290
275
|
expect(article?.getAttribute('aria-label')).toBe('Test Title lenkekort')
|
|
276
|
+
expect(article).toHaveClass('pkt-card--clickable')
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
test('renders an arrow after the link in the heading', async () => {
|
|
280
|
+
const { card } = await createCardTest({ heading: 'Test Title' })
|
|
281
|
+
card.clickCardLink = '/test-url'
|
|
282
|
+
await card.updateComplete
|
|
283
|
+
|
|
284
|
+
const icon = card.querySelector('.pkt-card__link-heading > .pkt-card__link-icon')
|
|
285
|
+
expect(icon).toBeInTheDocument()
|
|
286
|
+
expect(icon?.getAttribute('name')).toBe('arrow-link')
|
|
287
|
+
expect(icon?.previousElementSibling).toHaveClass('pkt-card__link')
|
|
291
288
|
})
|
|
292
289
|
|
|
293
290
|
test('handles openLinkInNewTab correctly', async () => {
|
|
@@ -338,20 +335,18 @@ describe('PktCard', () => {
|
|
|
338
335
|
expect(imageDiv).not.toBeInTheDocument()
|
|
339
336
|
})
|
|
340
337
|
|
|
341
|
-
test('applies
|
|
342
|
-
const
|
|
338
|
+
test('applies image aspect class only when imageAspect is set', async () => {
|
|
339
|
+
const { card } = await createCardTest()
|
|
340
|
+
card.image = { src: '/test.jpg', alt: 'Test' }
|
|
341
|
+
await card.updateComplete
|
|
343
342
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
card.image = { src: '/test.jpg', alt: 'Test' }
|
|
347
|
-
card.imageShape = shape
|
|
348
|
-
await card.updateComplete
|
|
343
|
+
const imageDiv = card.querySelector('.pkt-card__image')
|
|
344
|
+
expect(Array.from(imageDiv?.classList ?? [])).toEqual(['pkt-card__image'])
|
|
349
345
|
|
|
350
|
-
|
|
346
|
+
card.imageAspect = '16-9'
|
|
347
|
+
await card.updateComplete
|
|
351
348
|
|
|
352
|
-
|
|
353
|
-
expect(imageDiv).toHaveClass(`pkt-card__image-${shape}`)
|
|
354
|
-
}
|
|
349
|
+
expect(card.querySelector('.pkt-card__image')).toHaveClass('pkt-card__image-aspect-16-9')
|
|
355
350
|
})
|
|
356
351
|
})
|
|
357
352
|
|
|
@@ -483,7 +478,9 @@ describe('PktCard', () => {
|
|
|
483
478
|
await card.updateComplete
|
|
484
479
|
|
|
485
480
|
const article = card.querySelector('article')
|
|
486
|
-
|
|
481
|
+
expect(article?.children).toHaveLength(1)
|
|
482
|
+
expect(article?.firstElementChild).toHaveClass('pkt-card__container')
|
|
483
|
+
const children = Array.from(article?.firstElementChild?.children || [])
|
|
487
484
|
|
|
488
485
|
// Should have image first, then wrapper
|
|
489
486
|
expect(children[0]).toHaveClass('pkt-card__image')
|
|
@@ -11,6 +11,7 @@ import '@/components/icon'
|
|
|
11
11
|
import '@/components/tag'
|
|
12
12
|
import {
|
|
13
13
|
CARD_DEFAULTS,
|
|
14
|
+
CARD_LIGHT_ONLY_SKINS,
|
|
14
15
|
CARD_SKINS,
|
|
15
16
|
type IAriaAttributes,
|
|
16
17
|
type TCardSkin,
|
|
@@ -19,8 +20,6 @@ import {
|
|
|
19
20
|
import { plural, type IPktStringsProps } from 'shared-strings'
|
|
20
21
|
|
|
21
22
|
export type { TCardSkin, TLayout }
|
|
22
|
-
export type TCardPadding = 'none' | 'default'
|
|
23
|
-
export type TCardImageShape = 'square' | 'round'
|
|
24
23
|
export type TCardImageAspect = 'auto' | '1-1' | '4-3' | '3-2' | '16-9' | '19-10'
|
|
25
24
|
export type TCardTagPosition = 'top' | 'bottom'
|
|
26
25
|
|
|
@@ -32,14 +31,10 @@ export interface IPktCard extends IPktStringsProps<'card'> {
|
|
|
32
31
|
heading?: string
|
|
33
32
|
headingLevel?: IPktHeading['level']
|
|
34
33
|
image?: { src: string; alt: string }
|
|
35
|
-
imageShape?: TCardImageShape
|
|
36
34
|
imageAspect?: TCardImageAspect | null
|
|
37
|
-
restrictImageHeight?: boolean | null
|
|
38
35
|
clickCardLink?: string | null
|
|
39
36
|
openLinkInNewTab?: boolean | null
|
|
40
|
-
borderOnHover?: boolean | null
|
|
41
37
|
zoom?: boolean | null
|
|
42
|
-
padding?: TCardPadding
|
|
43
38
|
skin?: TCardSkin
|
|
44
39
|
subheading?: string
|
|
45
40
|
tagPosition?: TCardTagPosition
|
|
@@ -51,10 +46,8 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
|
|
|
51
46
|
|
|
52
47
|
@property({ type: String }) ariaLabel: string = ''
|
|
53
48
|
@property({ type: String }) metaLead: string | null = null
|
|
54
|
-
@property({ type: Boolean }) borderOnHover: boolean = CARD_DEFAULTS.borderOnHover
|
|
55
49
|
@property({ type: Boolean }) zoom: boolean = CARD_DEFAULTS.zoom
|
|
56
50
|
@property({ type: String }) imageAspect: TCardImageAspect | null = null
|
|
57
|
-
@property({ type: Boolean }) restrictImageHeight: boolean = CARD_DEFAULTS.restrictImageHeight
|
|
58
51
|
@property({ type: String, reflect: true }) clickCardLink: IPktCard['clickCardLink'] = null
|
|
59
52
|
@property({ type: String }) metaTrail: string | null = null
|
|
60
53
|
@property({ type: String }) layout: TLayout = CARD_DEFAULTS.layout
|
|
@@ -66,9 +59,7 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
|
|
|
66
59
|
src: '',
|
|
67
60
|
alt: '',
|
|
68
61
|
}
|
|
69
|
-
@property({ type: String }) imageShape: TCardImageShape = CARD_DEFAULTS.imageShape
|
|
70
62
|
@property({ type: Boolean }) openLinkInNewTab: boolean = CARD_DEFAULTS.openLinkInNewTab
|
|
71
|
-
@property({ type: String }) padding: TCardPadding = CARD_DEFAULTS.padding
|
|
72
63
|
|
|
73
64
|
@property({
|
|
74
65
|
type: String,
|
|
@@ -107,10 +98,8 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
|
|
|
107
98
|
'pkt-card': true,
|
|
108
99
|
[`pkt-card--${this.skin}`]: this.skin,
|
|
109
100
|
[`pkt-card--${this.layout}`]: this.layout,
|
|
110
|
-
[`pkt-card--
|
|
111
|
-
[`pkt-card--border-on-hover`]: this.borderOnHover,
|
|
101
|
+
[`pkt-card--clickable`]: !!this.clickCardLink,
|
|
112
102
|
[`pkt-card--zoom`]: this.zoom,
|
|
113
|
-
|
|
114
103
|
}
|
|
115
104
|
|
|
116
105
|
//
|
|
@@ -122,14 +111,17 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
|
|
|
122
111
|
<article
|
|
123
112
|
class=${classMap(classes)}
|
|
124
113
|
aria-label=${ifDefined(this.clickCardLink ? ariaLabelLenke : ariaLabelVanlig)}
|
|
114
|
+
data-mode=${ifDefined(CARD_LIGHT_ONLY_SKINS.includes(this.skin) ? 'light' : undefined)}
|
|
125
115
|
>
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
116
|
+
<div class="pkt-card__container">
|
|
117
|
+
${this.renderImage()}
|
|
118
|
+
<div class="pkt-card__wrapper">
|
|
119
|
+
${this.tagPosition === 'top' ? this.renderTags() : nothing}
|
|
120
|
+
${this.renderHeader()}
|
|
121
|
+
${this.renderSlot()}
|
|
122
|
+
${this.tagPosition === 'bottom' ? this.renderTags() : nothing}
|
|
123
|
+
${this.renderMetadata()}
|
|
124
|
+
</div>
|
|
133
125
|
</div>
|
|
134
126
|
</article>
|
|
135
127
|
`
|
|
@@ -139,9 +131,7 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
|
|
|
139
131
|
renderImage() {
|
|
140
132
|
const imageClasses = {
|
|
141
133
|
'pkt-card__image': true,
|
|
142
|
-
[`pkt-card__image-${this.imageShape}`]: this.imageShape,
|
|
143
134
|
[`pkt-card__image-aspect-${this.imageAspect}`]: Boolean(this.imageAspect),
|
|
144
|
-
'pkt-card__image-restricted': this.restrictImageHeight,
|
|
145
135
|
}
|
|
146
136
|
|
|
147
137
|
return html`
|
|
@@ -160,7 +150,7 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
|
|
|
160
150
|
const level =
|
|
161
151
|
this.headingLevel && this.headingLevel >= 1 && this.headingLevel <= 6 ? this.headingLevel : 3
|
|
162
152
|
// Bruker pkt-heading sine klasser her, for å unngå forskjeller i markup
|
|
163
|
-
const all = `pkt-heading pkt-heading--medium pkt-heading--fw-
|
|
153
|
+
const all = `pkt-heading pkt-heading--medium pkt-heading--fw-medium ${classes}`
|
|
164
154
|
switch (level) {
|
|
165
155
|
case 1:
|
|
166
156
|
return html`<h1 class=${all}>${content}</h1>`
|
|
@@ -193,7 +183,7 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
|
|
|
193
183
|
target=${this.openLinkInNewTab ? '_blank' : '_self'}
|
|
194
184
|
rel=${ifDefined(this.openLinkInNewTab ? 'noopener noreferrer' : undefined)}
|
|
195
185
|
>${this.heading}</a
|
|
196
|
-
>`,
|
|
186
|
+
><pkt-icon class="pkt-card__link-icon" name="arrow-link"></pkt-icon>`,
|
|
197
187
|
)
|
|
198
188
|
}
|
|
199
189
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { PktCard } from './card'
|
|
2
|
-
import type { TCardSkin, TLayout,
|
|
3
|
-
export { PktCard, TCardSkin, TLayout,
|
|
2
|
+
import type { TCardSkin, TLayout, TCardTagPosition } from './card'
|
|
3
|
+
export { PktCard, TCardSkin, TLayout, TCardTagPosition }
|
|
4
4
|
export default PktCard
|
|
@@ -409,7 +409,7 @@ describe('PktCheckbox', () => {
|
|
|
409
409
|
|
|
410
410
|
expect(checkbox.optionalTag).toBe(true)
|
|
411
411
|
|
|
412
|
-
const optionalTag = checkbox.querySelector('.pkt-tag--blue-
|
|
412
|
+
const optionalTag = checkbox.querySelector('.pkt-tag--blue-pale')
|
|
413
413
|
expect(optionalTag).toBeInTheDocument()
|
|
414
414
|
expect(optionalTag?.textContent).toBe('Valgfritt')
|
|
415
415
|
})
|
|
@@ -445,7 +445,7 @@ describe('PktCheckbox', () => {
|
|
|
445
445
|
expect(checkbox.optionalText).toBe('Custom Optional')
|
|
446
446
|
expect(checkbox.requiredText).toBe('Custom Required')
|
|
447
447
|
|
|
448
|
-
const optionalTag = checkbox.querySelector('.pkt-tag--blue-
|
|
448
|
+
const optionalTag = checkbox.querySelector('.pkt-tag--blue-pale')
|
|
449
449
|
const requiredTag = checkbox.querySelector('.pkt-tag--beige')
|
|
450
450
|
expect(optionalTag?.textContent).toBe('Custom Optional')
|
|
451
451
|
expect(requiredTag?.textContent).toBe('Custom Required')
|
|
@@ -463,7 +463,7 @@ describe('PktCheckbox', () => {
|
|
|
463
463
|
await checkbox.updateComplete
|
|
464
464
|
|
|
465
465
|
const customTag = checkbox.querySelector('.pkt-tag--gray')
|
|
466
|
-
const optionalTag = checkbox.querySelector('.pkt-tag--blue-
|
|
466
|
+
const optionalTag = checkbox.querySelector('.pkt-tag--blue-pale')
|
|
467
467
|
const requiredTag = checkbox.querySelector('.pkt-tag--beige')
|
|
468
468
|
|
|
469
469
|
expect(customTag).toBeInTheDocument()
|
|
@@ -133,7 +133,7 @@ export class PktCheckbox extends PktInputElement<Props> {
|
|
|
133
133
|
}
|
|
134
134
|
${
|
|
135
135
|
this.optionalTag
|
|
136
|
-
? html`<span class=${tagClasses + ' pkt-tag--blue-
|
|
136
|
+
? html`<span class=${tagClasses + ' pkt-tag--blue-pale'}
|
|
137
137
|
>${this.optionalText ?? formStrings.optional}</span
|
|
138
138
|
>`
|
|
139
139
|
: nothing
|
|
@@ -141,7 +141,7 @@ export class PktInputWrapper extends PktElementWithSlot<Props> implements IPktIn
|
|
|
141
141
|
? html`<span class=${tagClasses + ' pkt-tag--gray'}>${this.tagText}</span>`
|
|
142
142
|
: nothing}
|
|
143
143
|
${this.optionalTag
|
|
144
|
-
? html`<span class=${tagClasses + ' pkt-tag--blue-
|
|
144
|
+
? html`<span class=${tagClasses + ' pkt-tag--blue-pale'}
|
|
145
145
|
>${this.optionalText ?? formStrings.optional}</span
|
|
146
146
|
>`
|
|
147
147
|
: nothing}
|
|
@@ -16,7 +16,7 @@ export interface LinkTestConfig extends BaseTestConfig {
|
|
|
16
16
|
iconName?: string
|
|
17
17
|
iconPosition?: string
|
|
18
18
|
openInNewTab?: boolean
|
|
19
|
-
|
|
19
|
+
rel?: string
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
// Use shared framework
|
|
@@ -63,7 +63,7 @@ describe('PktLink', () => {
|
|
|
63
63
|
await link.updateComplete
|
|
64
64
|
|
|
65
65
|
expect(link.href).toBe('#')
|
|
66
|
-
expect(link.
|
|
66
|
+
expect(link.rel).toBeNull()
|
|
67
67
|
expect(link.iconName).toBeUndefined()
|
|
68
68
|
expect(link.target).toBe('_self')
|
|
69
69
|
})
|
|
@@ -79,14 +79,14 @@ describe('PktLink', () => {
|
|
|
79
79
|
expect(anchor?.href).toBe('https://example.com/')
|
|
80
80
|
})
|
|
81
81
|
|
|
82
|
-
test('sets
|
|
82
|
+
test('sets rel property correctly', async () => {
|
|
83
83
|
const { link } = await createLinkTest({
|
|
84
84
|
href: 'https://example.com',
|
|
85
|
-
|
|
85
|
+
rel: 'noopener noreferrer',
|
|
86
86
|
})
|
|
87
87
|
await link.updateComplete
|
|
88
88
|
|
|
89
|
-
expect(link.
|
|
89
|
+
expect(link.rel).toBe('noopener noreferrer')
|
|
90
90
|
})
|
|
91
91
|
})
|
|
92
92
|
|
|
@@ -116,16 +116,15 @@ describe('PktLink', () => {
|
|
|
116
116
|
})
|
|
117
117
|
})
|
|
118
118
|
|
|
119
|
-
describe('
|
|
120
|
-
test('
|
|
119
|
+
describe('Rel attribute', () => {
|
|
120
|
+
test('passes rel to the anchor', async () => {
|
|
121
121
|
const { link } = await createLinkTest({
|
|
122
122
|
href: 'https://example.com',
|
|
123
|
-
|
|
123
|
+
rel: 'noopener noreferrer',
|
|
124
124
|
})
|
|
125
125
|
await link.updateComplete
|
|
126
126
|
|
|
127
127
|
const anchor = link.querySelector('a')
|
|
128
|
-
expect(anchor?.classList.contains('pkt-link--external')).toBe(true)
|
|
129
128
|
expect(anchor?.rel).toBe('noopener noreferrer')
|
|
130
129
|
})
|
|
131
130
|
|
|
@@ -171,19 +170,16 @@ describe('PktLink', () => {
|
|
|
171
170
|
expect(anchor?.href).toBe('https://updated.com/')
|
|
172
171
|
})
|
|
173
172
|
|
|
174
|
-
test('updates
|
|
173
|
+
test('updates rel property dynamically', async () => {
|
|
175
174
|
const { link } = await createLinkTest({
|
|
176
175
|
href: 'https://example.com',
|
|
177
176
|
})
|
|
178
177
|
await link.updateComplete
|
|
179
178
|
|
|
180
|
-
link.
|
|
179
|
+
link.rel = 'noopener noreferrer'
|
|
181
180
|
await link.updateComplete
|
|
182
181
|
|
|
183
|
-
expect(link.
|
|
184
|
-
const anchor = link.querySelector('a')
|
|
185
|
-
expect(anchor?.classList.contains('pkt-link--external')).toBe(true)
|
|
186
|
-
expect(anchor?.rel).toBe('noopener noreferrer')
|
|
182
|
+
expect(link.querySelector('a')?.rel).toBe('noopener noreferrer')
|
|
187
183
|
})
|
|
188
184
|
})
|
|
189
185
|
|
|
@@ -206,7 +202,7 @@ describe('PktLink', () => {
|
|
|
206
202
|
href: 'https://external-site.com',
|
|
207
203
|
iconName: 'external',
|
|
208
204
|
iconPosition: 'right',
|
|
209
|
-
|
|
205
|
+
rel: 'noopener noreferrer',
|
|
210
206
|
target: '_blank',
|
|
211
207
|
content: 'Complex External Link',
|
|
212
208
|
})
|
|
@@ -214,11 +210,11 @@ describe('PktLink', () => {
|
|
|
214
210
|
|
|
215
211
|
expect(link.href).toBe('https://external-site.com')
|
|
216
212
|
expect(link.iconName).toBe('external')
|
|
217
|
-
expect(link.
|
|
213
|
+
expect(link.rel).toBe('noopener noreferrer')
|
|
218
214
|
expect(link.target).toBe('_blank')
|
|
219
215
|
|
|
220
216
|
const anchor = link.querySelector('a')
|
|
221
|
-
expect(anchor?.
|
|
217
|
+
expect(anchor?.rel).toBe('noopener noreferrer')
|
|
222
218
|
expect(anchor?.classList.contains('pkt-link--icon-right')).toBe(true)
|
|
223
219
|
})
|
|
224
220
|
})
|
|
@@ -17,7 +17,7 @@ export class PktLink extends PktElementWithSlot {
|
|
|
17
17
|
@property({ type: String, reflect: true }) href: string = specDefaults.href.default as string
|
|
18
18
|
@property({ type: String, reflect: true }) iconName: string | undefined = undefined
|
|
19
19
|
@property({ type: String, reflect: true }) iconPosition: string | undefined = undefined
|
|
20
|
-
@property({ type:
|
|
20
|
+
@property({ type: String, reflect: true }) rel: string | null = null
|
|
21
21
|
@property({ type: String, reflect: true }) target: string | null =
|
|
22
22
|
specDefaults.target.default as string
|
|
23
23
|
|
|
@@ -28,7 +28,6 @@ export class PktLink extends PktElementWithSlot {
|
|
|
28
28
|
(!!this.iconName && this.iconPosition === 'left') ||
|
|
29
29
|
!!(this.iconName && !this.iconPosition),
|
|
30
30
|
'pkt-link--icon-right': !!this.iconName && this.iconPosition === 'right',
|
|
31
|
-
'pkt-link--external': this.external,
|
|
32
31
|
}
|
|
33
32
|
const target = this.target && this.target !== '_self' ? this.target : nothing
|
|
34
33
|
|
|
@@ -36,7 +35,7 @@ export class PktLink extends PktElementWithSlot {
|
|
|
36
35
|
class=${classMap(classes)}
|
|
37
36
|
href=${this.href}
|
|
38
37
|
target=${target}
|
|
39
|
-
|
|
38
|
+
rel=${this.rel || nothing}
|
|
40
39
|
>${this.iconName
|
|
41
40
|
? html`<pkt-icon name=${this.iconName} class="pkt-link__icon"></pkt-icon>`
|
|
42
41
|
: ''}${slotContent(this)}</a
|
|
@@ -28,13 +28,14 @@ expect.extend(toHaveNoViolations)
|
|
|
28
28
|
|
|
29
29
|
// Test data constants
|
|
30
30
|
const VALID_SKINS: TLinkCardSkin[] = [
|
|
31
|
-
'
|
|
32
|
-
'
|
|
31
|
+
'gray',
|
|
32
|
+
'outlined',
|
|
33
|
+
'transparent',
|
|
34
|
+
'white',
|
|
33
35
|
'blue',
|
|
34
|
-
'beige',
|
|
35
36
|
'green',
|
|
36
|
-
'
|
|
37
|
-
'
|
|
37
|
+
'beige',
|
|
38
|
+
'normal',
|
|
38
39
|
'gray-outline',
|
|
39
40
|
]
|
|
40
41
|
|
|
@@ -65,7 +66,6 @@ describe('PktLinkCard', () => {
|
|
|
65
66
|
expect(linkCard.iconName).toBe('')
|
|
66
67
|
expect(linkCard.openInNewTab).toBe(false)
|
|
67
68
|
expect(linkCard.skin).toBeUndefined()
|
|
68
|
-
expect(linkCard.external).toBe(false)
|
|
69
69
|
|
|
70
70
|
expect(link.getAttribute('href')).toBe('#')
|
|
71
71
|
expect(link.getAttribute('target')).toBe('_self')
|
|
@@ -221,6 +221,18 @@ describe('PktLinkCard', () => {
|
|
|
221
221
|
}
|
|
222
222
|
})
|
|
223
223
|
|
|
224
|
+
test('keeps light-only skins in light mode', async () => {
|
|
225
|
+
for (const skin of ['white', 'blue', 'green', 'beige'] as const) {
|
|
226
|
+
const { link } = await createLinkCardTest({ skin })
|
|
227
|
+
expect(link).toHaveAttribute('data-mode', 'light')
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
for (const skin of ['gray', 'outlined', 'transparent', 'normal', 'gray-outline'] as const) {
|
|
231
|
+
const { link } = await createLinkCardTest({ skin })
|
|
232
|
+
expect(link).not.toHaveAttribute('data-mode')
|
|
233
|
+
}
|
|
234
|
+
})
|
|
235
|
+
|
|
224
236
|
test('handles skin property changes', async () => {
|
|
225
237
|
const { linkCard, link } = await createLinkCardTest({ skin: 'blue' })
|
|
226
238
|
|
|
@@ -4,7 +4,7 @@ import { PktElementWithSlot } from '@/base-elements/element-with-slot'
|
|
|
4
4
|
import { slotContent } from '@/directives/slot-content'
|
|
5
5
|
import '@/components/icon'
|
|
6
6
|
import { ifDefined } from 'lit/directives/if-defined.js'
|
|
7
|
-
import type
|
|
7
|
+
import { LINKCARD_LIGHT_ONLY_SKINS, type IPktLinkCardBase, type TLinkCardSkin } from 'shared-types'
|
|
8
8
|
|
|
9
9
|
export type { TLinkCardSkin }
|
|
10
10
|
|
|
@@ -14,7 +14,6 @@ export class PktLinkCard extends PktElementWithSlot<IPktLinkCard> implements IPk
|
|
|
14
14
|
@property({ type: String, reflect: true }) title: string = ''
|
|
15
15
|
@property({ type: String, reflect: true }) href: string = '#'
|
|
16
16
|
@property({ type: String, reflect: true }) iconName: string = ''
|
|
17
|
-
@property({ type: Boolean, reflect: true }) external: boolean = false
|
|
18
17
|
@property({ type: Boolean, reflect: true }) openInNewTab: boolean = false
|
|
19
18
|
@property({ type: String, reflect: true }) skin?: TLinkCardSkin = undefined
|
|
20
19
|
|
|
@@ -23,10 +22,6 @@ export class PktLinkCard extends PktElementWithSlot<IPktLinkCard> implements IPk
|
|
|
23
22
|
.filter(Boolean)
|
|
24
23
|
.join(' ')
|
|
25
24
|
|
|
26
|
-
const titleClasses = ['pkt-linkcard__title', this.external && 'pkt-link pkt-link--external']
|
|
27
|
-
.filter(Boolean)
|
|
28
|
-
.join(' ')
|
|
29
|
-
|
|
30
25
|
const s = this.pktStrings.get('linkcard')
|
|
31
26
|
const newTabLabel = this.openInNewTab ? s.openInNewTab : ''
|
|
32
27
|
|
|
@@ -34,11 +29,14 @@ export class PktLinkCard extends PktElementWithSlot<IPktLinkCard> implements IPk
|
|
|
34
29
|
<a
|
|
35
30
|
href=${this.href}
|
|
36
31
|
class=${classes}
|
|
32
|
+
data-mode=${ifDefined(
|
|
33
|
+
this.skin && LINKCARD_LIGHT_ONLY_SKINS.includes(this.skin) ? 'light' : undefined,
|
|
34
|
+
)}
|
|
37
35
|
target=${this.openInNewTab ? '_blank' : '_self'}
|
|
38
36
|
rel=${ifDefined(this.openInNewTab ? 'noopener noreferrer' : undefined)}
|
|
39
37
|
>
|
|
40
38
|
${this.iconName && html`<pkt-icon class="pkt-link__icon" name="${this.iconName}"></pkt-icon>`}
|
|
41
|
-
${this.title && html`<div class
|
|
39
|
+
${this.title && html`<div class="pkt-linkcard__title">${this.title}</div>`}
|
|
42
40
|
${newTabLabel ? html`<span class="pkt-sr-only">${newTabLabel}</span>` : ''}
|
|
43
41
|
|
|
44
42
|
<div class="pkt-linkcard__text">${slotContent(this)}</div>
|