@oslokommune/punkt-elements 19.14.3 → 19.15.3

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/calendar-5XCeDtZX.cjs +85 -0
  3. package/dist/{calendar-D9w8M99G.js → calendar-CtWc545R.js} +45 -60
  4. package/dist/{checkbox-group-adbFTj8y.cjs → checkbox-group-BLurd7sf.cjs} +1 -1
  5. package/dist/{checkbox-group-C8mo9dkO.js → checkbox-group-Bum7k828.js} +1 -1
  6. package/dist/{combobox-jsPpImVF.cjs → combobox-BsXDULXd.cjs} +1 -1
  7. package/dist/{combobox-B8IeuEF0.js → combobox-C7tUHbG4.js} +1 -1
  8. package/dist/components/modal/modal.d.ts +7 -0
  9. package/dist/components/modal/modal.test.d.ts +9 -0
  10. package/dist/{datepicker-CjUY_mLR.js → datepicker-CJLcIDVk.js} +2 -2
  11. package/dist/{datepicker-CZYpIyJd.cjs → datepicker-DmZi4CNk.cjs} +1 -1
  12. package/dist/docs/components/modal.d.ts +2 -0
  13. package/dist/{fileupload-CyLRyoVU.cjs → fileupload-A_suUEPU.cjs} +1 -1
  14. package/dist/{fileupload-BmfFC748.js → fileupload-DehKWas6.js} +2 -2
  15. package/dist/{header-BCrefip0.cjs → header-BzAPmAsZ.cjs} +1 -1
  16. package/dist/{header-20rqKJFb.js → header-C6xhv3Ib.js} +1 -1
  17. package/dist/{input-wrapper-BwzajfFX.cjs → input-wrapper-BEmV0DGo.cjs} +2 -3
  18. package/dist/{input-wrapper-Bb6CZxmg.js → input-wrapper-xRJo_iVf.js} +2 -3
  19. package/dist/{modal-B3CQEBBB.js → modal-0D0paY70.js} +42 -23
  20. package/dist/modal-wEEmCcUx.cjs +39 -0
  21. package/dist/{option-group-element-CzehfgVZ.cjs → option-group-element-A2cOZRWA.cjs} +1 -1
  22. package/dist/{option-group-element-D5PgGNdt.js → option-group-element-fpMneBWa.js} +1 -1
  23. package/dist/pkt-calendar.cjs +1 -1
  24. package/dist/pkt-calendar.js +1 -1
  25. package/dist/pkt-checkbox-group.cjs +1 -1
  26. package/dist/pkt-checkbox-group.js +1 -1
  27. package/dist/pkt-combobox.cjs +1 -1
  28. package/dist/pkt-combobox.js +1 -1
  29. package/dist/pkt-datepicker.cjs +1 -1
  30. package/dist/pkt-datepicker.js +1 -1
  31. package/dist/pkt-fileupload.cjs +1 -1
  32. package/dist/pkt-fileupload.js +1 -1
  33. package/dist/pkt-header.cjs +1 -1
  34. package/dist/pkt-header.js +1 -1
  35. package/dist/pkt-index.cjs +1 -1
  36. package/dist/pkt-index.js +13 -13
  37. package/dist/pkt-input-wrapper.cjs +1 -1
  38. package/dist/pkt-input-wrapper.js +1 -1
  39. package/dist/pkt-modal.cjs +1 -1
  40. package/dist/pkt-modal.js +1 -1
  41. package/dist/pkt-radio-group.cjs +1 -1
  42. package/dist/pkt-radio-group.js +1 -1
  43. package/dist/pkt-select.cjs +1 -1
  44. package/dist/pkt-select.js +1 -1
  45. package/dist/pkt-textarea.cjs +1 -1
  46. package/dist/pkt-textarea.js +1 -1
  47. package/dist/pkt-textinput.cjs +1 -1
  48. package/dist/pkt-textinput.js +1 -1
  49. package/dist/pkt-timepicker.cjs +1 -1
  50. package/dist/pkt-timepicker.js +1 -1
  51. package/dist/{radio-group-CtZhXMF8.js → radio-group-BmJ3kcba.js} +1 -1
  52. package/dist/{radio-group-MxNLGu-0.cjs → radio-group-Q75EtJzu.cjs} +1 -1
  53. package/dist/{select-Bs-Z5Thd.js → select-ByPSk9WT.js} +1 -1
  54. package/dist/{select-Czz1y2nI.cjs → select-CCY2_EbI.cjs} +1 -1
  55. package/dist/shared-types/calendar.d.ts +0 -1
  56. package/dist/shared-utils/calendar/calendar-grid.d.ts +0 -4
  57. package/dist/shared-utils/calendar/index.d.ts +1 -1
  58. package/dist/{textarea-C-sdNBRk.cjs → textarea-D9RWiR6u.cjs} +1 -1
  59. package/dist/{textarea-COHaMHpP.js → textarea-DB7FMtTf.js} +1 -1
  60. package/dist/{textinput-0DZeMqBr.js → textinput-Djl_yr1D.js} +1 -1
  61. package/dist/{textinput-BqBgsBZF.cjs → textinput-l31MdBd4.cjs} +1 -1
  62. package/dist/{timepicker-C_k-K1jA.cjs → timepicker-Bw8zkwV9.cjs} +1 -1
  63. package/dist/{timepicker-CvdI7jDN.js → timepicker-D_gNCZ2v.js} +1 -1
  64. package/package.json +2 -2
  65. package/src/components/calendar/calendar.constraints.test.ts +15 -0
  66. package/src/components/calendar/calendar.core.test.ts +15 -0
  67. package/src/components/calendar/calendar.ts +7 -15
  68. package/src/components/input-wrapper/input-wrapper.test.ts +1 -0
  69. package/src/components/input-wrapper/input-wrapper.ts +2 -2
  70. package/src/components/modal/modal.test.ts +141 -0
  71. package/src/components/modal/modal.ts +24 -5
  72. package/dist/calendar-C5QwPrbk.cjs +0 -91
  73. package/dist/modal-BKeSXrzi.cjs +0 -35
@@ -1,2 +1,2 @@
1
- import { t as e } from "./timepicker-CvdI7jDN.js";
1
+ import { t as e } from "./timepicker-D_gNCZ2v.js";
2
2
  export { e as PktTimepicker };
@@ -1,6 +1,6 @@
1
1
  import { d as e, l as t, n, u as r } from "./element-DBugHPKM.js";
2
2
  import { r as i } from "./radiobutton-BK-V6Itu.js";
3
- import { i as a, n as o, t as s } from "./option-group-element-D5PgGNdt.js";
3
+ import { i as a, n as o, t as s } from "./option-group-element-fpMneBWa.js";
4
4
  import { t as c } from "./provide-_MnlMGnw.js";
5
5
  //#region src/components/radio-group/radio-group.ts
6
6
  var l = class extends s {
@@ -1 +1 @@
1
- const e=require("./element-C6WTyJFE.cjs"),t=require("./radiobutton-DwDErNo5.cjs"),n=require("./option-group-element-CzehfgVZ.cjs"),r=require("./provide-Cz18sYug.cjs");var i=class extends n.t{constructor(...e){super(...e),this.optionSelector=`pkt-radiobutton`,this.groupContext={name:``,hasTile:!1,hasError:!1,required:!1},this.storedValue=null}get value(){let e=this.options().find(n.n);return e?n.i(e):``}set value(e){let t=this.value;this.storedValue=e??``,this.applyStoredValue(this.options()),this.requestUpdate(`value`,t)}get hasStoredValue(){return this.storedValue!==null}storeCurrentValue(){this.storedValue=this.value}applyStoredValue(e){e.forEach(e=>{let t=this.storedValue!==``&&n.i(e)===this.storedValue;n.n(e)!==t&&(e.checked=t)})}createGroupContext(){return{...super.createGroupContext(),required:this.required}}};e.n([r.t({context:t.r}),e.l()],i.prototype,`groupContext`,void 0),e.n([e.u({type:String})],i.prototype,`value`,null);try{e.d(`pkt-radio-group`)(i)}catch{console.warn(`Forsøker å definere <pkt-radio-group>, men den er allerede definert`)}var a=i;Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return a}});
1
+ const e=require("./element-C6WTyJFE.cjs"),t=require("./radiobutton-DwDErNo5.cjs"),n=require("./option-group-element-A2cOZRWA.cjs"),r=require("./provide-Cz18sYug.cjs");var i=class extends n.t{constructor(...e){super(...e),this.optionSelector=`pkt-radiobutton`,this.groupContext={name:``,hasTile:!1,hasError:!1,required:!1},this.storedValue=null}get value(){let e=this.options().find(n.n);return e?n.i(e):``}set value(e){let t=this.value;this.storedValue=e??``,this.applyStoredValue(this.options()),this.requestUpdate(`value`,t)}get hasStoredValue(){return this.storedValue!==null}storeCurrentValue(){this.storedValue=this.value}applyStoredValue(e){e.forEach(e=>{let t=this.storedValue!==``&&n.i(e)===this.storedValue;n.n(e)!==t&&(e.checked=t)})}createGroupContext(){return{...super.createGroupContext(),required:this.required}}};e.n([r.t({context:t.r}),e.l()],i.prototype,`groupContext`,void 0),e.n([e.u({type:String})],i.prototype,`value`,null);try{e.d(`pkt-radio-group`)(i)}catch{console.warn(`Forsøker å definere <pkt-radio-group>, men den er allerede definert`)}var a=i;Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return a}});
@@ -4,7 +4,7 @@ import { t as o } from "./if-defined-O59_I-e-.js";
4
4
  import { n as s, t as c } from "./ref-y_5qv9vU.js";
5
5
  import { t as l } from "./input-element-mTphzs9b.js";
6
6
  import { t as u } from "./pkt-options-controller-CHosj1Oo.js";
7
- import { r as d } from "./input-wrapper-Bb6CZxmg.js";
7
+ import { r as d } from "./input-wrapper-xRJo_iVf.js";
8
8
  //#region src/base-elements/options-input-element.ts
9
9
  var f = class extends l {
10
10
  constructor(...e) {
@@ -1,4 +1,4 @@
1
- const e=require("./element-C6WTyJFE.cjs"),t=require("./element-with-slot-CcJPCLgn.cjs"),n=require("./if-defined-CiML3MTM.cjs"),r=require("./ref-CB7e9nMY.cjs"),i=require("./input-element-BjnKPikY.cjs"),a=require("./pkt-options-controller-139UsV4h.cjs"),o=require("./input-wrapper-BwzajfFX.cjs");var s=class extends i.t{constructor(...e){super(...e),this._optionsProp=[],this._options=[]}get options(){return this._options.map(e=>({...e,selected:this.isOptionSelected(e)}))}set options(e){this._optionsProp=e,this.requestUpdate(`_optionsProp`,this._options)}isOptionSelected(e){return Array.isArray(this.value)?this.value.includes(e.value):e.value===this.value}findOptionByValue(e){return this._options.find(t=>t.value===e)}getSelectedOptions(){return this._options.filter(e=>this.isOptionSelected(e))}parseOptions(){let e=this._optionsProp.length>0,t=this.optionsController?.nodes?.length&&this.optionsController.nodes.length>0;e?this._options=this._optionsProp:t&&(this._options=this.optionsController.options)}willUpdate(e){super.willUpdate(e),this.parseOptions()}};e.n([e.u({type:Array,attribute:`options`})],s.prototype,`_optionsProp`,void 0),e.n([e.l()],s.prototype,`_options`,void 0);var c=class extends s{constructor(){super(),this.inputRef=r.t(),this.value=``,this.selectedIndex=-1,this.selectedOptions=void 0,this.optionsController=new a.t(this)}connectedCallback(){super.connectedCallback(),this.parseOptions(),this._options.forEach(e=>{e.selected&&!this.value&&(this.value=e.value)})}add(e,t){let n={value:e.value||e.text,label:e.text||e.value,selected:e.selected,disabled:e.disabled};if(t===void 0)this._options.push(n);else if(typeof t==`number`)this._options.splice(t,0,n);else{let e=t.value||t.text,r=this._options.findIndex(t=>t.value===e);r>=0?this._options.splice(r,0,n):this._options.push(n)}e.selected&&(this.value=e.value||e.text,this.selectedIndex=this._options.findIndex(e=>e.value===this.value)),this.requestUpdate()}remove(e){typeof e==`number`&&(this.selectedIndex===e&&(this.value=this._options[0]?.value||``),this._options.splice(e,1),this.requestUpdate())}item(e){return this.inputRef.value?.item(e)}namedItem(e){return this.inputRef.value?.namedItem(e)}showPicker(){this.inputRef.value&&`showPicker`in this.inputRef.value&&this.inputRef.value.showPicker()}attributeChangedCallback(e,t,n){e===`options`&&(this._options=n?JSON.parse(n):[]),e===`value`&&this.value!==t&&(this.selectedIndex=this.touched?this.returnNumberOrNull(this.inputRef.value?.selectedIndex):this._options.findIndex(e=>e.value===n),this.selectedOptions=this.inputRef.value?.selectedOptions,this.valueChanged(n,t)),super.attributeChangedCallback(e,t,n)}update(e){super.update(e),e.has(`_optionsProp`)&&this._optionsProp.length>0&&(this._options=this._optionsProp,this.requestUpdate(`_options`),!this.value&&this._options.length>0&&(this.value=this._options[0].value,this.selectedIndex=0)),e.has(`value`)&&this.value!==e.get(`value`)&&(this.selectedIndex=this.touched?this.returnNumberOrNull(this.inputRef.value?.selectedIndex):this._options.findIndex(e=>e.value===this.value),this.selectedOptions=this.inputRef.value?.selectedOptions,this.valueChanged(this.value,e.get(`value`))),e.has(`id`)&&!this.name&&this.id&&(this.name=this.id)}firstUpdated(e){super.firstUpdated(e),this.classList.add(`pkt-select`),this._optionsProp.length&&(this._options=this._optionsProp),!this.value&&this._options.length>0?(this.value=this._options[0].value,this.selectedIndex=0):this.selectedIndex=this._options.findIndex(e=>e.value===this.value),this.selectedOptions=this.inputRef.value?.selectedOptions}render(){let i=`pkt-input pkt-input--${this.inputSize} ${this.fullwidth?`pkt-input--fullwidth`:``}`;return e._`
1
+ const e=require("./element-C6WTyJFE.cjs"),t=require("./element-with-slot-CcJPCLgn.cjs"),n=require("./if-defined-CiML3MTM.cjs"),r=require("./ref-CB7e9nMY.cjs"),i=require("./input-element-BjnKPikY.cjs"),a=require("./pkt-options-controller-139UsV4h.cjs"),o=require("./input-wrapper-BEmV0DGo.cjs");var s=class extends i.t{constructor(...e){super(...e),this._optionsProp=[],this._options=[]}get options(){return this._options.map(e=>({...e,selected:this.isOptionSelected(e)}))}set options(e){this._optionsProp=e,this.requestUpdate(`_optionsProp`,this._options)}isOptionSelected(e){return Array.isArray(this.value)?this.value.includes(e.value):e.value===this.value}findOptionByValue(e){return this._options.find(t=>t.value===e)}getSelectedOptions(){return this._options.filter(e=>this.isOptionSelected(e))}parseOptions(){let e=this._optionsProp.length>0,t=this.optionsController?.nodes?.length&&this.optionsController.nodes.length>0;e?this._options=this._optionsProp:t&&(this._options=this.optionsController.options)}willUpdate(e){super.willUpdate(e),this.parseOptions()}};e.n([e.u({type:Array,attribute:`options`})],s.prototype,`_optionsProp`,void 0),e.n([e.l()],s.prototype,`_options`,void 0);var c=class extends s{constructor(){super(),this.inputRef=r.t(),this.value=``,this.selectedIndex=-1,this.selectedOptions=void 0,this.optionsController=new a.t(this)}connectedCallback(){super.connectedCallback(),this.parseOptions(),this._options.forEach(e=>{e.selected&&!this.value&&(this.value=e.value)})}add(e,t){let n={value:e.value||e.text,label:e.text||e.value,selected:e.selected,disabled:e.disabled};if(t===void 0)this._options.push(n);else if(typeof t==`number`)this._options.splice(t,0,n);else{let e=t.value||t.text,r=this._options.findIndex(t=>t.value===e);r>=0?this._options.splice(r,0,n):this._options.push(n)}e.selected&&(this.value=e.value||e.text,this.selectedIndex=this._options.findIndex(e=>e.value===this.value)),this.requestUpdate()}remove(e){typeof e==`number`&&(this.selectedIndex===e&&(this.value=this._options[0]?.value||``),this._options.splice(e,1),this.requestUpdate())}item(e){return this.inputRef.value?.item(e)}namedItem(e){return this.inputRef.value?.namedItem(e)}showPicker(){this.inputRef.value&&`showPicker`in this.inputRef.value&&this.inputRef.value.showPicker()}attributeChangedCallback(e,t,n){e===`options`&&(this._options=n?JSON.parse(n):[]),e===`value`&&this.value!==t&&(this.selectedIndex=this.touched?this.returnNumberOrNull(this.inputRef.value?.selectedIndex):this._options.findIndex(e=>e.value===n),this.selectedOptions=this.inputRef.value?.selectedOptions,this.valueChanged(n,t)),super.attributeChangedCallback(e,t,n)}update(e){super.update(e),e.has(`_optionsProp`)&&this._optionsProp.length>0&&(this._options=this._optionsProp,this.requestUpdate(`_options`),!this.value&&this._options.length>0&&(this.value=this._options[0].value,this.selectedIndex=0)),e.has(`value`)&&this.value!==e.get(`value`)&&(this.selectedIndex=this.touched?this.returnNumberOrNull(this.inputRef.value?.selectedIndex):this._options.findIndex(e=>e.value===this.value),this.selectedOptions=this.inputRef.value?.selectedOptions,this.valueChanged(this.value,e.get(`value`))),e.has(`id`)&&!this.name&&this.id&&(this.name=this.id)}firstUpdated(e){super.firstUpdated(e),this.classList.add(`pkt-select`),this._optionsProp.length&&(this._options=this._optionsProp),!this.value&&this._options.length>0?(this.value=this._options[0].value,this.selectedIndex=0):this.selectedIndex=this._options.findIndex(e=>e.value===this.value),this.selectedOptions=this.inputRef.value?.selectedOptions}render(){let i=`pkt-input pkt-input--${this.inputSize} ${this.fullwidth?`pkt-input--fullwidth`:``}`;return e._`
2
2
  <pkt-input-wrapper
3
3
  ${t.n(this,[`helptext`])}
4
4
  .strings=${this.strings}
@@ -84,7 +84,6 @@ export interface ICalendarGridDimensions {
84
84
  startingDay: number;
85
85
  numDays: number;
86
86
  numRows: number;
87
- numDaysPrevMonth: number;
88
87
  initialWeek: number;
89
88
  }
90
89
  export interface IGridCellPosition {
@@ -10,7 +10,3 @@ export declare function calculateCalendarDimensions(year: number, month: number)
10
10
  * Determine what type of cell to render at a given position
11
11
  */
12
12
  export declare function getCellType(rowIndex: number, colIndex: number, dayCounter: number, gridDimensions: ICalendarGridDimensions): 'prev-month' | 'current-month' | 'next-month';
13
- /**
14
- * Get the day number to display for a given cell
15
- */
16
- export declare function getDayNumber(cellType: 'prev-month' | 'current-month' | 'next-month', colIndex: number, dayCounter: number, gridDimensions: ICalendarGridDimensions): number;
@@ -5,6 +5,6 @@
5
5
  * to provide a single import point for calendar-related utilities.
6
6
  */
7
7
  export { isDateExcluded, isDayDisabled, isPrevMonthAllowed, isNextMonthAllowed, type IDateConstraints, } from './date-validation';
8
- export { DAYS_PER_WEEK, MONDAY_OFFSET, calculateCalendarDimensions, getCellType, getDayNumber, type ICalendarGridDimensions, type IGridCellPosition, } from './calendar-grid';
8
+ export { DAYS_PER_WEEK, MONDAY_OFFSET, calculateCalendarDimensions, getCellType, type ICalendarGridDimensions, type IGridCellPosition, } from './calendar-grid';
9
9
  export { convertSelectedToDates, updateRangeMap, isRangeAllowed, addToSelection, removeFromSelection, toggleSelection, handleRangeSelection, type TDateRangeMap, type ISelectionState, type ISelectionOptions, } from './selection-manager';
10
10
  export { KEY_DIRECTION_MAP, shouldIgnoreKeyboardEvent, findNextSelectableDate, getKeyDirection, } from './keyboard-navigation';
@@ -1,4 +1,4 @@
1
- const e=require("./element-C6WTyJFE.cjs"),t=require("./class-map-Bh6toDeV.cjs"),n=require("./directive-helpers-Bv70GjQh.cjs"),r=require("./element-with-slot-CcJPCLgn.cjs");require("./icon-jPhyZD1z.cjs");const i=require("./if-defined-CiML3MTM.cjs"),a=require("./ref-CB7e9nMY.cjs"),o=require("./input-element-BjnKPikY.cjs"),s=require("./input-wrapper-BwzajfFX.cjs");var c=e.f(class extends e.p{constructor(t){if(super(t),t.type!==e.m.PROPERTY&&t.type!==e.m.ATTRIBUTE&&t.type!==e.m.BOOLEAN_ATTRIBUTE)throw Error("The `live` directive is not allowed on child or event bindings");if(!n.i(t))throw Error("`live` bindings can only contain a single expression")}render(e){return e}update(t,[r]){if(r===e.g||r===e.h)return r;let i=t.element,a=t.name;if(t.type===e.m.PROPERTY){if(r===i[a])return e.g}else if(t.type===e.m.BOOLEAN_ATTRIBUTE){if(!!r===i.hasAttribute(a))return e.g}else if(t.type===e.m.ATTRIBUTE&&i.getAttribute(a)===r+``)return e.g;return n.r(t),r}}),l=class extends o.t{constructor(...e){super(...e),this.inputRef=a.t(),this.value=``,this.autocomplete=`off`,this.rows=null,this.cols=null,this.counterCurrent=0}attributeChangedCallback(e,t,n){e===`value`&&this.value!==t&&(this.counterCurrent=n?n.length:0),super.attributeChangedCallback(e,t,n)}willUpdate(e){super.willUpdate(e),e.has(`value`)&&(this.counterCurrent=this.value?.length||0),e.has(`id`)&&!this.name&&this.id&&(this.name=this.id)}updated(e){super.updated(e),this.classList.add(`pkt-textinput`,`pkt-textarea`),e.has(`value`)&&this.valueChanged(this.value,e.get(`value`))}render(){let n=this.effectiveCounter(this.counterMaxLength>0),o=t.t({"pkt-input":!0,[`pkt-input--${this.inputSize}`]:!0,"pkt-input--fullwidth":this.fullwidth,"pkt-input--counter-error":n&&this.counterMaxLength>0&&this.value.length>this.counterMaxLength}),l=this.ariaLabelledby||`${this.id}-input-label`;return e._`<pkt-input-wrapper
1
+ const e=require("./element-C6WTyJFE.cjs"),t=require("./class-map-Bh6toDeV.cjs"),n=require("./directive-helpers-Bv70GjQh.cjs"),r=require("./element-with-slot-CcJPCLgn.cjs");require("./icon-jPhyZD1z.cjs");const i=require("./if-defined-CiML3MTM.cjs"),a=require("./ref-CB7e9nMY.cjs"),o=require("./input-element-BjnKPikY.cjs"),s=require("./input-wrapper-BEmV0DGo.cjs");var c=e.f(class extends e.p{constructor(t){if(super(t),t.type!==e.m.PROPERTY&&t.type!==e.m.ATTRIBUTE&&t.type!==e.m.BOOLEAN_ATTRIBUTE)throw Error("The `live` directive is not allowed on child or event bindings");if(!n.i(t))throw Error("`live` bindings can only contain a single expression")}render(e){return e}update(t,[r]){if(r===e.g||r===e.h)return r;let i=t.element,a=t.name;if(t.type===e.m.PROPERTY){if(r===i[a])return e.g}else if(t.type===e.m.BOOLEAN_ATTRIBUTE){if(!!r===i.hasAttribute(a))return e.g}else if(t.type===e.m.ATTRIBUTE&&i.getAttribute(a)===r+``)return e.g;return n.r(t),r}}),l=class extends o.t{constructor(...e){super(...e),this.inputRef=a.t(),this.value=``,this.autocomplete=`off`,this.rows=null,this.cols=null,this.counterCurrent=0}attributeChangedCallback(e,t,n){e===`value`&&this.value!==t&&(this.counterCurrent=n?n.length:0),super.attributeChangedCallback(e,t,n)}willUpdate(e){super.willUpdate(e),e.has(`value`)&&(this.counterCurrent=this.value?.length||0),e.has(`id`)&&!this.name&&this.id&&(this.name=this.id)}updated(e){super.updated(e),this.classList.add(`pkt-textinput`,`pkt-textarea`),e.has(`value`)&&this.valueChanged(this.value,e.get(`value`))}render(){let n=this.effectiveCounter(this.counterMaxLength>0),o=t.t({"pkt-input":!0,[`pkt-input--${this.inputSize}`]:!0,"pkt-input--fullwidth":this.fullwidth,"pkt-input--counter-error":n&&this.counterMaxLength>0&&this.value.length>this.counterMaxLength}),l=this.ariaLabelledby||`${this.id}-input-label`;return e._`<pkt-input-wrapper
2
2
  ${r.n(this,[`helptext`])}
3
3
  .strings=${this.strings}
4
4
  label=${this.label}
@@ -6,7 +6,7 @@ import "./icon-Bao96Zb8.js";
6
6
  import { t as m } from "./if-defined-O59_I-e-.js";
7
7
  import { n as h, t as g } from "./ref-y_5qv9vU.js";
8
8
  import { t as _ } from "./input-element-mTphzs9b.js";
9
- import { r as v } from "./input-wrapper-Bb6CZxmg.js";
9
+ import { r as v } from "./input-wrapper-xRJo_iVf.js";
10
10
  //#region ../../node_modules/lit-html/directives/live.js
11
11
  var y = n(class extends c {
12
12
  constructor(e) {
@@ -5,7 +5,7 @@ import "./icon-Bao96Zb8.js";
5
5
  import { t as c } from "./if-defined-O59_I-e-.js";
6
6
  import { n as l, t as u } from "./ref-y_5qv9vU.js";
7
7
  import { t as d } from "./input-element-mTphzs9b.js";
8
- import { r as f } from "./input-wrapper-Bb6CZxmg.js";
8
+ import { r as f } from "./input-wrapper-xRJo_iVf.js";
9
9
  //#region src/components/textinput/textinput.ts
10
10
  var p = class extends d {
11
11
  constructor(...e) {
@@ -1,4 +1,4 @@
1
- const e=require("./element-C6WTyJFE.cjs"),t=require("./class-map-Bh6toDeV.cjs"),n=require("./element-with-slot-CcJPCLgn.cjs");require("./icon-jPhyZD1z.cjs");const r=require("./if-defined-CiML3MTM.cjs"),i=require("./ref-CB7e9nMY.cjs"),a=require("./input-element-BjnKPikY.cjs"),o=require("./input-wrapper-BwzajfFX.cjs");var s=class extends a.t{constructor(...e){super(...e),this.inputRef=i.t(),this.value=``,this.type=`text`,this.size=null,this.autocomplete=null,this.iconNameRight=null,this.prefix=null,this.suffix=null,this.omitSearchIcon=!1,this.counterCurrent=0}attributeChangedCallback(e,t,n){e===`value`&&this.value!==t&&(this.counterCurrent=n?n.length:0),super.attributeChangedCallback(e,t,n)}willUpdate(e){super.willUpdate(e),e.has(`value`)&&(this.counterCurrent=this.value?.length||0),e.has(`id`)&&!this.name&&this.id&&(this.name=this.id)}updated(e){super.updated(e),this.classList.add(`pkt-textinput`),e.has(`value`)&&this.valueChanged(this.value,e.get(`value`))}render(){let a=this.type===`search`&&!this.iconNameRight&&!this.omitSearchIcon,s=this.effectiveCounter(this.counterMaxLength>0),c=t.t({"pkt-input":!0,[`pkt-input--${this.inputSize}`]:!0,"pkt-input--fullwidth":this.fullwidth,"pkt-input--counter-error":s&&this.counterMaxLength>0&&this.value.length>this.counterMaxLength}),l=this.ariaLabelledby||`${this.id}-input-label`;return e._`
1
+ const e=require("./element-C6WTyJFE.cjs"),t=require("./class-map-Bh6toDeV.cjs"),n=require("./element-with-slot-CcJPCLgn.cjs");require("./icon-jPhyZD1z.cjs");const r=require("./if-defined-CiML3MTM.cjs"),i=require("./ref-CB7e9nMY.cjs"),a=require("./input-element-BjnKPikY.cjs"),o=require("./input-wrapper-BEmV0DGo.cjs");var s=class extends a.t{constructor(...e){super(...e),this.inputRef=i.t(),this.value=``,this.type=`text`,this.size=null,this.autocomplete=null,this.iconNameRight=null,this.prefix=null,this.suffix=null,this.omitSearchIcon=!1,this.counterCurrent=0}attributeChangedCallback(e,t,n){e===`value`&&this.value!==t&&(this.counterCurrent=n?n.length:0),super.attributeChangedCallback(e,t,n)}willUpdate(e){super.willUpdate(e),e.has(`value`)&&(this.counterCurrent=this.value?.length||0),e.has(`id`)&&!this.name&&this.id&&(this.name=this.id)}updated(e){super.updated(e),this.classList.add(`pkt-textinput`),e.has(`value`)&&this.valueChanged(this.value,e.get(`value`))}render(){let a=this.type===`search`&&!this.iconNameRight&&!this.omitSearchIcon,s=this.effectiveCounter(this.counterMaxLength>0),c=t.t({"pkt-input":!0,[`pkt-input--${this.inputSize}`]:!0,"pkt-input--fullwidth":this.fullwidth,"pkt-input--counter-error":s&&this.counterMaxLength>0&&this.value.length>this.counterMaxLength}),l=this.ariaLabelledby||`${this.id}-input-label`;return e._`
2
2
  <pkt-input-wrapper
3
3
  ${n.n(this,[`helptext`])}
4
4
  .strings=${this.strings}
@@ -1,4 +1,4 @@
1
- const e=require("./element-C6WTyJFE.cjs"),t=require("./class-map-Bh6toDeV.cjs"),n=require("./format-B8meU8Tm.cjs"),r=require("./element-with-slot-CcJPCLgn.cjs");require("./icon-jPhyZD1z.cjs");const i=require("./if-defined-CiML3MTM.cjs"),a=require("./ref-CB7e9nMY.cjs"),o=require("./input-element-BjnKPikY.cjs"),s=require("./input-wrapper-BwzajfFX.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 o.t{constructor(...e){super(...e),this.hiddenInputRef=a.t(),this.hoursInputRef=a.t(),this.minutesInputRef=a.t(),this.buttonRef=a.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);return}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);return}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);return}this.internals.setValidity({}),this._setAriaInvalid(!1)}_describedBy(){return s.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-C6WTyJFE.cjs"),t=require("./class-map-Bh6toDeV.cjs"),n=require("./format-B8meU8Tm.cjs"),r=require("./element-with-slot-CcJPCLgn.cjs");require("./icon-jPhyZD1z.cjs");const i=require("./if-defined-CiML3MTM.cjs"),a=require("./ref-CB7e9nMY.cjs"),o=require("./input-element-BjnKPikY.cjs"),s=require("./input-wrapper-BEmV0DGo.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 o.t{constructor(...e){super(...e),this.hiddenInputRef=a.t(),this.hoursInputRef=a.t(),this.minutesInputRef=a.t(),this.buttonRef=a.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);return}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);return}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);return}this.internals.setValidity({}),this._setAriaInvalid(!1)}_describedBy(){return s.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"
@@ -6,7 +6,7 @@ import "./icon-Bao96Zb8.js";
6
6
  import { t as l } from "./if-defined-O59_I-e-.js";
7
7
  import { n as u, t as d } from "./ref-y_5qv9vU.js";
8
8
  import { t as f } from "./input-element-mTphzs9b.js";
9
- import { r as p } from "./input-wrapper-Bb6CZxmg.js";
9
+ import { r as p } from "./input-wrapper-xRJo_iVf.js";
10
10
  //#region ../../shared-utils/timepicker/time-utils.ts
11
11
  var m = (e) => /^\d{2}:\d{2}$/.test(e) && parseInt(e.slice(0, 2), 10) <= 23 && parseInt(e.slice(3), 10) <= 59, h = (e) => {
12
12
  let [t, n] = e.split(":").map(Number);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oslokommune/punkt-elements",
3
- "version": "19.14.3",
3
+ "version": "19.15.3",
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",
@@ -84,5 +84,5 @@
84
84
  "engines": {
85
85
  "node": "^22.19.0 || ^24.0.0 || ^26.0.0"
86
86
  },
87
- "gitHead": "c81c6cf722332d44ad8590517eb989fc8d46b33d"
87
+ "gitHead": "e4314e8b6bd5119bb74094fa2809fc5d389bcd2e"
88
88
  }
@@ -41,6 +41,21 @@ describe('PktCalendar', () => {
41
41
  expect(disabledDates.length).toBeGreaterThan(0)
42
42
  })
43
43
 
44
+ test('marks month navigation as disabled outside earliest and latest', async () => {
45
+ const container = await createCalendar(
46
+ 'earliest="2024-10-05" latest="2024-10-25" currentmonth="2024-10-01"',
47
+ )
48
+
49
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
50
+ await calendar.updateComplete
51
+
52
+ for (const selector of ['.pkt-calendar__prev-month', '.pkt-calendar__next-month']) {
53
+ const button = calendar.querySelector(selector)
54
+ expect(button).toHaveAttribute('aria-disabled', 'true')
55
+ expect(button).toHaveAttribute('data-disabled', 'disabled')
56
+ }
57
+ })
58
+
44
59
  test('handles latest date property correctly', async () => {
45
60
  const latestDate = '2024-12-15'
46
61
  const container = await createCalendar(`latest="${latestDate}"`)
@@ -52,6 +52,18 @@ describe('PktCalendar', () => {
52
52
  expect(monthNav).toBeInTheDocument()
53
53
  })
54
54
 
55
+ test('renders days outside the current month as empty cells', async () => {
56
+ const container = await createCalendar('currentmonth="2024-10-01"')
57
+
58
+ const calendar = container.querySelector('pkt-calendar') as PktCalendar
59
+ await calendar.updateComplete
60
+
61
+ const otherCells = calendar.querySelectorAll('.pkt-cal-other')
62
+ expect(otherCells).toHaveLength(4)
63
+ otherCells.forEach((cell) => expect(cell).toBeEmptyDOMElement())
64
+ expect(calendar.querySelectorAll('.pkt-calendar__date')).toHaveLength(31)
65
+ })
66
+
55
67
  test('renders month picker when withcontrols is true', async () => {
56
68
  const container = await createCalendar('withcontrols')
57
69
 
@@ -113,6 +125,7 @@ describe('PktCalendar', () => {
113
125
  expect(calendar.selected).toEqual([])
114
126
  expect(calendar.earliest).toBe(null)
115
127
  expect(calendar.latest).toBe(null)
128
+ expect(calendar.querySelector('[role="grid"]')).not.toHaveAttribute('aria-multiselectable')
116
129
  })
117
130
 
118
131
  test('handles multiple property correctly', async () => {
@@ -122,6 +135,7 @@ describe('PktCalendar', () => {
122
135
  await calendar.updateComplete
123
136
 
124
137
  expect(calendar.multiple).toBe(true)
138
+ expect(calendar.querySelector('[role="grid"]')).toHaveAttribute('aria-multiselectable', 'true')
125
139
  })
126
140
 
127
141
  test('handles range property correctly', async () => {
@@ -131,6 +145,7 @@ describe('PktCalendar', () => {
131
145
  await calendar.updateComplete
132
146
 
133
147
  expect(calendar.range).toBe(true)
148
+ expect(calendar.querySelector('[role="grid"]')).toHaveAttribute('aria-multiselectable', 'true')
134
149
  })
135
150
 
136
151
  test('handles weeknumbers property correctly', async () => {
@@ -25,7 +25,6 @@ import {
25
25
  DAYS_PER_WEEK,
26
26
  calculateCalendarDimensions,
27
27
  getCellType,
28
- getDayNumber,
29
28
  } from 'shared-utils/calendar/calendar-grid'
30
29
  import {
31
30
  convertSelectedToDates,
@@ -256,7 +255,7 @@ export class PktCalendar extends PktElement<IPktStringsProps<'dates' | 'calendar
256
255
  <table
257
256
  class="pkt-cal-days pkt-txt-12-medium pkt-calendar__body"
258
257
  role="grid"
259
- ?aria-multiselectable=${this.range || this.multiple}
258
+ aria-multiselectable=${this.range || this.multiple ? 'true' : nothing}
260
259
  >
261
260
  <thead>
262
261
  ${this.renderDayNames()}
@@ -290,8 +289,8 @@ export class PktCalendar extends PktElement<IPktStringsProps<'dates' | 'calendar
290
289
  }
291
290
  }}
292
291
  class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--icon-only ${className} ${isAllowed ? '' : 'pkt-invisible'}"
293
- .data-disabled=${!isAllowed ? 'disabled' : nothing}
294
- ?aria-disabled=${!isAllowed}
292
+ data-disabled=${!isAllowed ? 'disabled' : nothing}
293
+ aria-disabled=${!isAllowed ? 'true' : nothing}
295
294
  tabindex=${isAllowed ? '0' : '-1'}
296
295
  >
297
296
  <pkt-icon class="pkt-btn__icon" name="${iconName}"></pkt-icon>
@@ -356,6 +355,7 @@ export class PktCalendar extends PktElement<IPktStringsProps<'dates' | 'calendar
356
355
  const target = e.target as HTMLInputElement
357
356
  this.changeMonth(parseInt(target.value), this.month)
358
357
  }}
358
+ value=${this.year}
359
359
  .value=${this.year}
360
360
  />
361
361
  </div>`
@@ -505,15 +505,8 @@ export class PktCalendar extends PktElement<IPktStringsProps<'dates' | 'calendar
505
505
  </td>`
506
506
  }
507
507
 
508
- private renderEmptyDayCell(day: number): TemplateResult {
509
- return html`<td class="pkt-cal-other">
510
- <div
511
- class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--label-only"
512
- data-disabled="disabled"
513
- >
514
- <span class="pkt-btn__text pkt-txt-14-light">${day}</span>
515
- </div>
516
- </td>`
508
+ private renderEmptyDayCell(): TemplateResult {
509
+ return html`<td class="pkt-cal-other"></td>`
517
510
  }
518
511
 
519
512
  private renderWeekRow(cells: TemplateResult[]): TemplateResult {
@@ -551,8 +544,7 @@ export class PktCalendar extends PktElement<IPktStringsProps<'dates' | 'calendar
551
544
  cells.push(this.renderDayView(dayCounter, today))
552
545
  dayCounter++
553
546
  } else {
554
- const dayNumber = getDayNumber(cellType, j, dayCounter, dimensions)
555
- cells.push(this.renderEmptyDayCell(dayNumber))
547
+ cells.push(this.renderEmptyDayCell())
556
548
  if (cellType === 'next-month') {
557
549
  dayCounter++
558
550
  }
@@ -197,6 +197,7 @@ describe('PktInputWrapper', () => {
197
197
 
198
198
  const counter = wrapper.querySelector('.pkt-input__counter')
199
199
  expect(counter).toBeInTheDocument()
200
+ expect(counter?.textContent?.trim()).toBe('5/100')
200
201
  })
201
202
 
202
203
  test('updates counter current value', async () => {
@@ -184,9 +184,9 @@ export class PktInputWrapper extends PktElementWithSlot<Props> {
184
184
  // Den synlige telleren er aria-hidden. Statusregionen under holdes tom
185
185
  // til grensa er brutt, så skjermlesere bare varsler når det faktisk er noe å si.
186
186
  const exceeded = isCounterExceeded(this.counterCurrent, this.counterMaxLength)
187
+ const count = `${this.counterCurrent || 0}${this.counterMaxLength ? `/${this.counterMaxLength}` : ''}`
187
188
  return html`<div class="pkt-input__counter" aria-hidden="true">
188
- ${this.counterError ? this.counterError : nothing} ${this.counterCurrent || 0}
189
- ${this.counterMaxLength ? `/${this.counterMaxLength}` : nothing}
189
+ ${this.counterError ? `${this.counterError} ` : nothing}${count}
190
190
  </div>
191
191
  <div class="pkt-sr-only" id=${counterStatusId(this.forId)} aria-live="polite">
192
192
  ${exceeded
@@ -0,0 +1,141 @@
1
+ import '@testing-library/jest-dom'
2
+ import { axe, toHaveNoViolations } from 'jest-axe'
3
+ import { createElementTest, BaseTestConfig } from '../../tests/test-framework'
4
+ import { CustomElementFor } from '../../tests/component-registry'
5
+ import type { IPktModal } from './modal'
6
+ import './modal'
7
+
8
+ expect.extend(toHaveNoViolations)
9
+
10
+ export interface ModalTestConfig extends IPktModal, BaseTestConfig {}
11
+
12
+ export const createModalTest = async (config: ModalTestConfig = {}) => {
13
+ const { container, element } = await createElementTest<
14
+ CustomElementFor<'pkt-modal'>,
15
+ ModalTestConfig
16
+ >('pkt-modal', config)
17
+
18
+ return {
19
+ container,
20
+ modal: element,
21
+ heading: element.querySelector('.pkt-modal__headingText'),
22
+ }
23
+ }
24
+
25
+ afterEach(() => {
26
+ document.body.innerHTML = ''
27
+ })
28
+
29
+ describe('PktModal', () => {
30
+ describe('heading icon', () => {
31
+ test('renders no icon by default', async () => {
32
+ const { heading } = await createModalTest({ headingText: 'Historikk' })
33
+ expect(heading).not.toHaveClass('pkt-modal__headingText--hasIcon')
34
+ expect(heading?.querySelector('pkt-icon')).toBeNull()
35
+ })
36
+
37
+ test('renders the icon before the heading text', async () => {
38
+ const { heading } = await createModalTest({
39
+ headingText: 'Historikk',
40
+ headingIconName: 'clock-history',
41
+ })
42
+ expect(heading).toHaveClass('pkt-modal__headingText--hasIcon')
43
+ const icon = heading?.firstElementChild
44
+ expect(icon?.tagName.toLowerCase()).toBe('pkt-icon')
45
+ expect(icon).toHaveClass('pkt-modal__headingIcon')
46
+ expect(icon).toHaveAttribute('name', 'clock-history')
47
+ expect(heading).toHaveTextContent('Historikk')
48
+ })
49
+
50
+ test('passes headingIconPath to the icon', async () => {
51
+ const customPath = 'https://custom-cdn.example.com/icons/'
52
+ const { modal } = await createModalTest({
53
+ headingText: 'Historikk',
54
+ headingIconName: 'clock-history',
55
+ headingIconPath: customPath,
56
+ })
57
+ expect(modal.headingIconPath).toBe(customPath)
58
+ const icon = modal.querySelector('.pkt-modal__headingIcon')
59
+ expect(icon).toHaveAttribute('path', customPath)
60
+ })
61
+
62
+ test('does not set the path attribute when headingIconPath is not provided', async () => {
63
+ const { modal } = await createModalTest({
64
+ headingText: 'Historikk',
65
+ headingIconName: 'clock-history',
66
+ })
67
+ const icon = modal.querySelector('.pkt-modal__headingIcon')
68
+ expect(icon).not.toHaveAttribute('path')
69
+ })
70
+
71
+ test('does not render the icon without headingText', async () => {
72
+ const { modal } = await createModalTest({ headingIconName: 'clock-history' })
73
+ expect(modal.querySelector('.pkt-modal__headingIcon')).toBeNull()
74
+ })
75
+
76
+ test('updates the icon when headingIconName changes', async () => {
77
+ const { modal } = await createModalTest({
78
+ headingText: 'Historikk',
79
+ headingIconName: 'clock-history',
80
+ })
81
+ modal.headingIconName = 'user'
82
+ await modal.updateComplete
83
+ expect(modal.querySelector('.pkt-modal__headingIcon')).toHaveAttribute('name', 'user')
84
+
85
+ modal.headingIconName = undefined
86
+ await modal.updateComplete
87
+ expect(modal.querySelector('.pkt-modal__headingIcon')).toBeNull()
88
+ expect(modal.querySelector('.pkt-modal__headingText')).not.toHaveClass(
89
+ 'pkt-modal__headingText--hasIcon',
90
+ )
91
+ })
92
+
93
+ test('renders with no wcag errors with axe', async () => {
94
+ const { container } = await createModalTest({
95
+ headingText: 'Historikk',
96
+ headingIconName: 'clock-history',
97
+ })
98
+ const results = await axe(container)
99
+ expect(results).toHaveNoViolations()
100
+ })
101
+ })
102
+
103
+ describe('ids', () => {
104
+ test('labels and describes the dialog with its own heading and content', async () => {
105
+ const { modal } = await createModalTest({ headingText: 'Historikk' })
106
+ const dialog = modal.querySelector('dialog')!
107
+ const heading = modal.querySelector('h1.pkt-modal__headingText')!
108
+ const content = modal.querySelector('.pkt-modal__content')!
109
+ expect(heading.id).toMatch(/^pkt-modal__headingText-/)
110
+ expect(content.id).toMatch(/^pkt-modal__content-/)
111
+ expect(dialog).toHaveAttribute('aria-labelledby', heading.id)
112
+ expect(dialog).toHaveAttribute('aria-describedby', content.id)
113
+ })
114
+
115
+ test('gives each modal on the page unique ids', async () => {
116
+ const { modal: first } = await createModalTest({ headingText: 'Første' })
117
+ const { modal: second } = await createModalTest({ headingText: 'Andre' })
118
+ const firstHeading = first.querySelector('h1')!
119
+ const secondHeading = second.querySelector('h1')!
120
+ expect(firstHeading.id).not.toBe(secondHeading.id)
121
+ expect(first.querySelector('dialog')).toHaveAttribute('aria-labelledby', firstHeading.id)
122
+ expect(second.querySelector('dialog')).toHaveAttribute('aria-labelledby', secondHeading.id)
123
+ expect(first.querySelector('dialog')!.getAttribute('aria-describedby')).not.toBe(
124
+ second.querySelector('dialog')!.getAttribute('aria-describedby'),
125
+ )
126
+ })
127
+
128
+ test('keeps the ids stable across re-renders', async () => {
129
+ const { modal } = await createModalTest({ headingText: 'Historikk' })
130
+ const before = modal.querySelector('h1')!.id
131
+ modal.headingText = 'Endret'
132
+ await modal.updateComplete
133
+ expect(modal.querySelector('h1')!.id).toBe(before)
134
+ })
135
+
136
+ test('omits aria-labelledby without headingText', async () => {
137
+ const { modal } = await createModalTest()
138
+ expect(modal.querySelector('dialog')).not.toHaveAttribute('aria-labelledby')
139
+ })
140
+ })
141
+ })
@@ -1,4 +1,5 @@
1
1
  import { classMap } from 'lit/directives/class-map.js'
2
+ import { ifDefined } from 'lit/directives/if-defined.js'
2
3
  import { customElement, property, state } from 'lit/decorators.js'
3
4
  import { html, nothing, PropertyValues } from 'lit'
4
5
  import { PktElementWithSlot } from '@/base-elements/element-with-slot'
@@ -11,6 +12,7 @@ import {
11
12
  setScrollLock,
12
13
  type ScrollLockToken,
13
14
  } from 'shared-utils/scroll-lock'
15
+ import { uuidish } from 'shared-utils/utils'
14
16
  import specs from 'componentSpecs/modal.json'
15
17
  import '@/components/icon'
16
18
 
@@ -19,6 +21,8 @@ type ModalSize = TPktSize | 'fit-content'
19
21
  export interface IPktModal {
20
22
  open?: boolean
21
23
  headingText?: string
24
+ headingIconName?: string
25
+ headingIconPath?: string
22
26
  removePadding?: boolean
23
27
  hideCloseButton?: boolean
24
28
  closeOnBackdropClick?: boolean
@@ -33,6 +37,8 @@ export class PktModal extends PktElementWithSlot implements IPktModal {
33
37
  // Public properties
34
38
  @property({ type: Boolean, reflect: true }) open?: boolean = false
35
39
  @property({ type: String }) headingText?: string = ''
40
+ @property({ type: String }) headingIconName?: string
41
+ @property({ type: String }) headingIconPath?: string
36
42
  @property({ type: Boolean }) removePadding?: boolean = false
37
43
  @property({ type: Boolean }) hideCloseButton?: boolean = specs.props.hideCloseButton.default
38
44
  @property({ type: Boolean })
@@ -47,6 +53,10 @@ export class PktModal extends PktElementWithSlot implements IPktModal {
47
53
 
48
54
  private _scrollLockToken: ScrollLockToken = createScrollLockToken()
49
55
 
56
+ private readonly _idSuffix = uuidish()
57
+ private readonly _headingId = `pkt-modal__headingText-${this._idSuffix}`
58
+ private readonly _contentId = `pkt-modal__content-${this._idSuffix}`
59
+
50
60
  @state() _isOpen: boolean = false
51
61
 
52
62
  constructor() {
@@ -164,8 +174,17 @@ export class PktModal extends PktElementWithSlot implements IPktModal {
164
174
  const headingClasses = {
165
175
  'pkt-modal__headingText': true,
166
176
  'pkt-txt-24': true,
177
+ 'pkt-modal__headingText--hasIcon': !!this.headingIconName,
167
178
  }
168
179
 
180
+ const headingIcon = this.headingIconName
181
+ ? html`<pkt-icon
182
+ class="pkt-modal__headingIcon"
183
+ name=${this.headingIconName}
184
+ path=${ifDefined(this.headingIconPath)}
185
+ ></pkt-icon>`
186
+ : nothing
187
+
169
188
  const contentClasses = {
170
189
  'pkt-modal__content': true,
171
190
  'pkt-txt-18-light': true,
@@ -181,8 +200,8 @@ export class PktModal extends PktElementWithSlot implements IPktModal {
181
200
  <dialog
182
201
  class=${classMap(classes)}
183
202
  ${ref(this.dialogRef)}
184
- aria-labelledby=${this.headingText ? 'pkt-modal__headingText' : nothing}
185
- aria-describedby="pkt-modal__content"
203
+ aria-labelledby=${this.headingText ? this._headingId : nothing}
204
+ aria-describedby=${this._contentId}
186
205
  @close=${(event: Event) => this.close(event, true)}
187
206
  >
188
207
  <div class="pkt-modal__wrapper">
@@ -190,8 +209,8 @@ export class PktModal extends PktElementWithSlot implements IPktModal {
190
209
  ? html`<div class="pkt-modal__header">
191
210
  <div class="pkt-modal__header-background"></div>
192
211
  ${this.headingText
193
- ? html`<h1 id="pkt-modal__headingText" class=${classMap(headingClasses)}>
194
- ${this.headingText}
212
+ ? html`<h1 id=${this._headingId} class=${classMap(headingClasses)}>
213
+ ${headingIcon}${this.headingText}
195
214
  </h1>`
196
215
  : html`<div class="pkt-modal__headingText"></div>`}
197
216
  ${!this.hideCloseButton
@@ -211,7 +230,7 @@ export class PktModal extends PktElementWithSlot implements IPktModal {
211
230
  </div>`
212
231
  : nothing}
213
232
  <div class="pkt-modal__container">
214
- <div id="pkt-modal__content" class=${classMap(contentClasses)}>
233
+ <div id=${this._contentId} class=${classMap(contentClasses)}>
215
234
  ${slotContent(this)}
216
235
  </div>
217
236
  </div>