@oslokommune/punkt-elements
Version:
Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo
90 lines • 19.8 kB
JavaScript
const e=require(`./element-DjtxO-1r.cjs`),t=require(`./class-map-CJ-msbHs.cjs`);require(`./icon-Dr8sfT2X.cjs`);const n=require(`./converters-Bffq_YDm.cjs`);function r(e,t,r){let i=n.y(e,r?.in);return isNaN(t)?n.b(r?.in||e,NaN):(t&&i.setDate(i.getDate()+t),i)}function i(e,t){let[r,i]=n.v(e,t.start,t.end);return{start:r,end:i}}function a(e,t){let{start:r,end:a}=i(t?.in,e),o=+r>+a,s=o?+r:+a,c=o?a:r;c.setHours(0,0,0,0);let l=t?.step??1;if(!l)return[];l<0&&(l=-l,o=!o);let u=[];for(;+c<=s;)u.push(n.b(r,c)),c.setDate(c.getDate()+l),c.setHours(0,0,0,0);return o?u.reverse():u}function o(e,t){let r=n.y(e,t?.in).getDay();return r===0?7:r}var s={name:`pkt-calendar`,react:`PktCalendar`,"css-class":`pkt-calendar`,isElement:!0,isPureReact:!0,props:{id:{type:`string`,name:`ID`,description:`Unik identifikasjon for kalenderen`},currentmonth:{type:`date`,name:`Gjeldende måned`,converter:`stringToDate`,description:`Måneden som vises i kalenderen`},selected:{type:`array`,name:`Valgte datoer`,converter:`csvToArray`,reflect:!0,items:{type:`date`},description:`Liste over valgte datoer`},excludeweekdays:{type:`array`,name:`Utelat ukedager`,converter:`csvToArray`,items:{type:`string`},description:`Liste over ukedager (1-7) som skal ekskluderes`},excludedates:{type:`array`,name:`Utelat datoer`,converter:`stringsToDate`,items:{type:`date`},description:`Liste over spesifikke datoer som skal ekskluderes`},earliest:{type:`date`,name:`Tidligst tillatte dato`,converter:`stringToDate`,default:null,description:`Tidligste dato som kan velges`},latest:{type:`date`,name:`Senest tillatte dato`,converter:`stringToDate`,default:null,description:`Seneste dato som kan velges`},weeknumbers:{type:`boolean`,name:`Vis ukenummer`,reflect:!0,default:!1,description:`Vis ukenummer i kalenderen`},withcontrols:{type:`boolean`,name:`Med velgere for måned/år`,reflect:!0,default:!1,description:`Vis navigasjonskontroller for måned og år`},multiple:{type:`boolean`,name:`Flervalg`,reflect:!0,default:!1,description:`Tillat valg av flere datoer`},maxMultiple:{attribute:`max-multiple`,type:`number`,name:`Maks antall i flervalg`,default:4,description:`Maksimalt antall datoer som kan velges`},today:{type:`string`,name:`Dagens dato (overstyring)`,description:`ISO-datostreng som overstyrer dagens dato. Nyttig for snapshot-tester.`},range:{type:`boolean`,name:`Datotidsrom (fra og til)`,reflect:!0,default:!1,description:`Tillat valg av datotidsrom`},dayStrings:{attribute:`day-strings`,type:`array`,name:`Korte dagsnavn`,items:{type:`string`},description:`Korte dagsnavn for kalenderoverskriften`},dayStringsLong:{attribute:`day-strings-long`,type:`array`,name:`Fulle dagsnavn`,items:{type:`string`},description:`Fulle dagsnavn for tilgjengelighetsetiketter`},monthStrings:{attribute:`month-strings`,type:`array`,name:`Månedsnavn`,items:{type:`string`},description:`Månedsnavn for kalendernavigasjonen`},weekString:{attribute:`week-string`,type:`string`,name:`Ukenummer-etikett`,description:`Etikett for ukenummerkolonnen`},prevMonthString:{attribute:`prev-month-string`,type:`string`,name:`Forrige måned-etikett`,description:`Tilgjengelighetsetikett for forrige måned-knappen`},nextMonthString:{attribute:`next-month-string`,type:`string`,name:`Neste måned-etikett`,description:`Tilgjengelighetsetikett for neste måned-knappen`}},events:{"date-selected":{description:`Returnerer en liste med valgte datoer i ISO-format`},close:{description:`Utløses når kalenderen ber om å lukkes (Escape-tast eller fokus forlater)`}}};function c(e,t){let r=(t.excludedates??[]).map(e=>typeof e==`string`?e:n.a(e));return!n.l(e,t.earliest,t.latest,r,t.excludeweekdays??[])}function l(e,t,n,r){return!!(c(e,n)||!t&&r.multiple&&r.maxMultiple>0&&r.selectedCount>=r.maxMultiple)}function u(e,t,r){let i=n.p(e,t,0);return!(r&&n.d(r)>i)}function d(e,t,r){let i=n.p(t===11?e+1:e,t===11?0:t+1,1);return!(r&&n.d(r)<i)}function f(e,t){let r=n.p(e,t,1),i=n.p(e,t+1,0),a=(r.getDay()+6)%7,o=i.getDate();return{firstDayOfMonth:r,lastDayOfMonth:i,startingDay:a,numDays:o,numRows:Math.ceil((o+a)/7),numDaysPrevMonth:n.p(e,t,0).getDate(),initialWeek:n._(r)}}function p(e,t,n,r){let{startingDay:i,numDays:a}=r;return e===0&&t<i?`prev-month`:n>a?`next-month`:`current-month`}function m(e,t,n,r){let{startingDay:i,numDaysPrevMonth:a,numDays:o}=r;return e===`prev-month`?a-(i-t-1):e===`next-month`?n-o:n}function h(e){return typeof e==`string`&&(e=e.split(`,`)),e.length===1&&e[0]===``?[]:e.map(e=>n.m(e))}function g(e,t){let r=a({start:e,end:t}),i={};if(Array.isArray(r)&&r.length)for(let a=0;a<r.length;a++){let o=r[a],s=o>e&&o<t;i[n.a(o)]=s}return i}function _(e,t,n,r){if(t.length!==1)return!0;let i=a({start:t[0],end:e});if(!Array.isArray(i)||!i.length)return!0;for(let a=0;a<i.length;a++){for(let r of n??[])if(r>t[0]&&r<e)return!1;if((r??[]).includes(o(i[a]).toString()))return!1}return!0}function v(e,t){let r=n.a(e);return t.includes(r)?t:[...t,r]}function y(e,t){let r=n.a(e),i=t.indexOf(r);if(i===-1)return t;if(t.length===1)return[];let a=[...t];return a.splice(i,1),a}function b(e,t,r){let i=n.a(e);return t.includes(i)?y(e,t):r>0&&t.length>=r?t:v(e,t)}function x(e,t,r){let i=n.a(e),a=h(t);return t.includes(i)?t.indexOf(i)===0?[]:y(e,t):t.length>1||t.length===1&&(!_(e,a,r.excludedates,r.excludeweekdays)||a[0]>e)?[i]:v(e,t)}var S={ArrowLeft:-1,ArrowRight:1,ArrowUp:-7,ArrowDown:7};function C(e){let t=e.nodeName;return t===`INPUT`||t===`SELECT`||t===`BUTTON`&&!e.dataset?.date}function w(e,t,i){let a=r(e,t);if(!a)return null;let o=i(`button[data-date="${n.a(a)}"]`);for(;o instanceof HTMLButtonElement&&o.dataset.disabled;)if(a=r(a,t),o=i(`button[data-date="${n.a(a)}"]`),!o)return null;return a}function T(e){return S[e]??null}var E=class extends e.t{constructor(...e){super(...e),this.selected=[],this.multiple=s.props.multiple.default,this.maxMultiple=s.props.maxMultiple.default,this.range=s.props.range.default,this.earliest=s.props.earliest.default,this.latest=s.props.latest.default,this.excludedates=[],this.excludeweekdays=[],this.weeknumbers=s.props.weeknumbers.default,this.withcontrols=s.props.withcontrols.default,this.currentmonth=null,this.today=null,this.dayStrings=this.strings.dates.daysShort,this.dayStringsLong=this.strings.dates.days,this.monthStrings=this.strings.dates.months,this.weekString=this.strings.dates.week,this.prevMonthString=this.strings.dates.prevMonth,this.nextMonthString=this.strings.dates.nextMonth,this._selected=[],this.inRange={},this.rangeHovered=null,this.year=0,this.month=0,this.week=0,this.currentmonthtouched=!1,this.focusedDate=null,this.selectableDates=[],this.tabIndexSet=0}get todayDate(){return this.today?n.m(this.today):n.g()}firstUpdated(e){this.addEventListener(`keydown`,this.handleKeydown)}disconnectedCallback(){this.removeEventListener(`keydown`,this.handleKeydown),super.disconnectedCallback()}updated(e){super.updated(e),e.has(`selected`)&&this.convertSelected()}convertSelected(){typeof this.selected==`string`&&(this.selected=this.selected.split(`,`)),this.selected.length===1&&this.selected[0]===``&&(this.selected=[]),this._selected=h(this.selected),this.range&&this.selected.length===2&&(this.inRange=g(this._selected[0],this._selected[1])),this.setCurrentMonth()}setCurrentMonth(){if(this.currentmonth===null&&!this.currentmonthtouched&&(this.currentmonthtouched=!0),this.selected.length&&this.selected[0]!==``){let e=n.m(this.selected[this.selected.length-1]);this.currentmonth=isNaN(e.getTime())?n.f(this.todayDate):e}else this.currentmonth===null&&(this.currentmonth=n.f(this.todayDate));(!this.currentmonth||isNaN(this.currentmonth.getTime()))&&(this.currentmonth=n.f(this.todayDate)),this.year=this.currentmonth.getFullYear(),this.month=this.currentmonth.getMonth()}handleKeydown(e){let t=T(e.key);t!==null&&this.handleArrowKey(e,t)}handleArrowKey(e,t){let r=e.target;if(C(r))return;if(e.preventDefault(),!this.focusedDate){this.focusOnCurrentDate();return}let i=w(this.focusedDate?n.d(this.focusedDate):n.p(this.year,this.month,1),t,this.querySelector.bind(this));if(i){let e=this.querySelector(`button[data-date="${n.a(i)}"]`);e instanceof HTMLButtonElement&&!e.dataset.disabled&&(this.focusedDate=n.a(i),e.focus())}}render(){return e.d`
<div
class="pkt-calendar ${this.weeknumbers?`pkt-cal-weeknumbers`:``}"
=${this.closeEvent}
=${e=>{e.key===`Escape`&&(e.preventDefault(),this.close())}}
>
<nav class="pkt-cal-month-nav">
${this.renderMonthNavButton(`prev`)}
${this.renderMonthNav()}
${this.renderMonthNavButton(`next`)}
</nav>
<table
class="pkt-cal-days pkt-txt-12-medium pkt-calendar__body"
role="grid"
?aria-multiselectable=${this.range||this.multiple}
>
<thead>
${this.renderDayNames()}
</thead>
<tbody>
${this.renderCalendarBody()}
</tbody>
</table>
</div>
`}renderMonthNavButton(t){let n=t===`prev`,r=n?this.isPrevMonthAllowed():this.isNextMonthAllowed(),i=n?this.prevMonthString:this.nextMonthString,a=n?`chevron-thin-left`:`chevron-thin-right`,o=n?`pkt-calendar__prev-month`:`pkt-calendar__next-month`,s=n?()=>this.prevMonth():()=>this.nextMonth();return e.d`<div>
<button
type="button"
aria-label="${i}"
=${()=>r&&s()}
=${e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),r&&s())}}
class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--icon-only ${o} ${r?``:`pkt-invisible`}"
.data-disabled=${r?e.l:`disabled`}
?aria-disabled=${!r}
tabindex=${r?`0`:`-1`}
>
<pkt-icon class="pkt-btn__icon" name="${a}"></pkt-icon>
<span class="pkt-btn__text">${i}</span>
</button>
</div>`}renderDayNames(){let t=[];this.weeknumbers&&t.push(e.d`<th><div class="pkt-calendar__week-number">${this.weekString}</div></th>`);for(let n=0;n<this.dayStrings.length;n++)t.push(e.d`<th>
<div class="pkt-calendar__day-name" aria-label="${this.dayStringsLong[n]}">
${this.dayStrings[n]}
</div>
</th>`);return e.d`<tr class="pkt-cal-week-row">${t}</tr>`}renderMonthNav(){return this.withcontrols?e.d`<div class="pkt-cal-month-picker">
<label for="${this.id}-monthnav" class="pkt-hide">${this.strings.dates.month}</label>
<select
aria-label="${this.strings.dates.month}"
class="pkt-input pkt-input-compact"
id="${this.id}-monthnav"
=${e=>{e.stopImmediatePropagation();let t=e.target;this.changeMonth(this.year,parseInt(t.value))}}
>
${this.monthStrings.map((t,n)=>e.d`<option value=${n} ?selected=${this.month===n}>${t}</option>`)}
</select>
<label for="${this.id}-yearnav" class="pkt-hide">${this.strings.dates.year}</label>
<input
aria-label="${this.strings.dates.year}"
class="pkt-input pkt-cal-input-year pkt-input-compact"
id="${this.id}-yearnav"
type="number"
size="4"
placeholder="0000"
=${e=>{e.stopImmediatePropagation();let t=e.target;this.changeMonth(parseInt(t.value),this.month)}}
.value=${this.year}
/>
</div>`:e.d`<div class="pkt-txt-16-medium pkt-calendar__month-title" aria-live="polite">
${this.monthStrings[this.month]} ${this.year}
</div>`}getDayViewData(e,t){let r=n.p(this.year,this.month,e),i=n.a(r),a=i===n.a(t),o=this.selected.includes(i),s=this.isDayDisabled(r,o),c=this.calculateTabIndex(i,s,e);return{currentDate:r,currentDateISO:i,isToday:a,isSelected:o,isDisabled:s,ariaLabel:n.o(r),tabindex:c}}getDateConstraints(){return{earliest:this.earliest,latest:this.latest,excludedates:this.excludedates,excludeweekdays:this.excludeweekdays}}isDayDisabled(e,t){return l(e,t,this.getDateConstraints(),{multiple:this.multiple,maxMultiple:this.maxMultiple,selectedCount:this.selected.length})}calculateTabIndex(e,t,n){return this.focusedDate?this.focusedDate===e&&!t?`0`:`-1`:!t&&this.tabIndexSet===0?(this.tabIndexSet=n,`0`):this.tabIndexSet===n?`0`:`-1`}getDayCellClasses(e){let{currentDateISO:t,isToday:r,isSelected:i}=e,a=this.range&&(this.selected.length===2||this.rangeHovered!==null)&&t===this.selected[0],o=this.range&&this.selected.length===2&&t===this.selected[1];return{"pkt-cal-today":r,"pkt-cal-selected":i,"pkt-cal-in-range":this.inRange[t],"pkt-cal-excluded":this.isExcluded(e.currentDate),"pkt-cal-in-range-first":a,"pkt-cal-in-range-last":o,"pkt-cal-range-hover":this.rangeHovered!==null&&t===n.a(this.rangeHovered)}}getDayButtonClasses(e){let{currentDateISO:t,isToday:r,isSelected:i,isDisabled:a}=e,o=this.range&&(this.selected.length===2||this.rangeHovered!==null)&&t===this.selected[0],s=this.range&&this.selected.length===2&&t===this.selected[1];return{"pkt-calendar__date":!0,"pkt-calendar__date--today":r,"pkt-calendar__date--selected":i,"pkt-calendar__date--disabled":a,"pkt-calendar__date--in-range":this.inRange[t],"pkt-calendar__date--in-range-hover":this.rangeHovered!==null&&t===n.a(this.rangeHovered),"pkt-calendar__date--range-start":o,"pkt-calendar__date--range-end":s}}handleDayFocus(e,t){this.range&&!this.isExcluded(e)&&this.handleRangeHover(e),this.focusedDate=t}renderDayView(n,r){let i=this.getDayViewData(n,r),{currentDate:a,currentDateISO:o,isSelected:s,isDisabled:c,ariaLabel:l,tabindex:u}=i;this.selectableDates.push({currentDateISO:o,isDisabled:c,tabindex:u});let d=this.getDayCellClasses(i),f=this.getDayButtonClasses(i);return e.d`<td class=${t.t(d)}>
<button
type="button"
aria-pressed=${s?`true`:`false`}
?disabled=${c}
class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--label-only ${t.t(f)}"
=${()=>this.range&&!this.isExcluded(a)&&this.handleRangeHover(a)}
=${()=>this.handleDayFocus(a,o)}
aria-label="${l}"
tabindex=${u}
data-disabled=${c?`disabled`:e.l}
data-date=${o}
=${e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),this.handleDateSelect(a))}}
=${e=>{c||(e.preventDefault(),this.handleDateSelect(a))}}
>
<span class="pkt-btn__text pkt-txt-14-light">${n}</span>
</button>
</td>`}renderEmptyDayCell(t){return e.d`<td class="pkt-cal-other">
<div
class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--label-only"
data-disabled="disabled"
>
<span class="pkt-btn__text pkt-txt-14-light">${t}</span>
</div>
</td>`}renderWeekRow(t){return e.d`<tr class="pkt-cal-week-row" role="row">${t}</tr>`}renderCalendarBody(){let t=this.todayDate,n=f(this.year,this.month);this.selectableDates=[],this.tabIndexSet=0;let r=1;this.week=n.initialWeek;let i=[];for(let a=0;a<n.numRows;a++){let o=[];this.weeknumbers&&o.push(e.d`<td class="pkt-cal-week">${this.week}</td>`),this.week++;for(let e=0;e<7;e++){let i=p(a,e,r,n);if(i===`current-month`)o.push(this.renderDayView(r,t)),r++;else{let t=m(i,e,r,n);o.push(this.renderEmptyDayCell(t)),i===`next-month`&&r++}}i.push(this.renderWeekRow(o))}return i}isExcluded(e){return c(e,this.getDateConstraints())}isPrevMonthAllowed(){return u(this.year,this.month,this.earliest)}prevMonth(){let e=this.month===0?11:this.month-1,t=this.month===0?this.year-1:this.year;this.changeMonth(t,e)}isNextMonthAllowed(){return d(this.year,this.month,this.latest)}nextMonth(){let e=this.month===11?0:this.month+1,t=this.month===11?this.year+1:this.year;this.changeMonth(t,e)}changeMonth(e,t){this.year=typeof e==`string`?parseInt(e):e,this.month=typeof t==`string`?parseInt(t):t,this.currentmonth=n.f(new Date(this.year,this.month,1)),this.tabIndexSet=0,this.focusedDate=null,this.selectableDates=[]}emptySelected(){this.selected=[],this._selected=[],this.inRange={}}normalizeSelected(){return typeof this.selected==`string`?this.selected.split(`,`):this.selected}addToSelected(e){this.selected=v(e,this.normalizeSelected()),this._selected=h(this.selected),this.range&&this.selected.length===2&&(this.convertSelected(),this.close())}removeFromSelected(e){this.selected=y(e,this.normalizeSelected()),this._selected=h(this.selected)}toggleSelected(e){this.selected=b(e,this.normalizeSelected(),this.maxMultiple),this._selected=h(this.selected)}isRangeAllowed(e){return _(e,this._selected,this.excludedates,this.excludeweekdays)}handleRangeSelect(e){return this.selected=x(e,this.normalizeSelected(),{excludedates:this.excludedates,excludeweekdays:this.excludeweekdays}),this._selected=h(this.selected),this.selected.length===2?(this.convertSelected(),this.close()):this.selected.length===1&&(this.inRange={}),Promise.resolve()}handleRangeHover(e){if(!this.range||this._selected.length!==1||!this.isRangeAllowed(e)||this._selected[0]>=e){this.rangeHovered=null;return}this.rangeHovered=e,this.inRange=g(this._selected[0],e)}handleDateSelect(e){return e?(this.range?this.handleRangeSelect(e):this.multiple?this.toggleSelected(e):(this.selected.includes(n.a(e))?this.emptySelected():(this.emptySelected(),this.addToSelected(e)),this.close()),this.dispatchEvent(new CustomEvent(`date-selected`,{detail:this.selected,bubbles:!0,composed:!0})),Promise.resolve()):Promise.resolve()}focusOnCurrentDate(){let e=n.a(n.f(this.todayDate)),t=this.querySelector(`button[data-date="${e}"]`);if(t instanceof HTMLButtonElement){this.focusedDate=e,t.focus();return}let r=this.selectableDates.find(e=>!e.isDisabled);if(r){let e=this.querySelector(`button[data-date="${r.currentDateISO}"]`);e instanceof HTMLButtonElement&&(this.focusedDate=r.currentDateISO,e.focus())}}closeEvent(e){!this.contains(e.relatedTarget)&&!e.target.classList.contains(`pkt-invisible`)&&this.close()}close(){this.dispatchEvent(new CustomEvent(`close`,{detail:!0,bubbles:!0,composed:!0}))}};e.r([e.s({converter:n.t.csvToArray})],E.prototype,`selected`,void 0),e.r([e.s({type:Boolean})],E.prototype,`multiple`,void 0),e.r([e.s({type:Number,attribute:`max-multiple`})],E.prototype,`maxMultiple`,void 0),e.r([e.s({type:Boolean})],E.prototype,`range`,void 0),e.r([e.s({type:String})],E.prototype,`earliest`,void 0),e.r([e.s({type:String})],E.prototype,`latest`,void 0),e.r([e.s({converter:n.t.stringsToDate})],E.prototype,`excludedates`,void 0),e.r([e.s({converter:n.t.csvToArray})],E.prototype,`excludeweekdays`,void 0),e.r([e.s({type:Boolean})],E.prototype,`weeknumbers`,void 0),e.r([e.s({type:Boolean})],E.prototype,`withcontrols`,void 0),e.r([e.s({converter:n.t.stringToDate})],E.prototype,`currentmonth`,void 0),e.r([e.s({type:String})],E.prototype,`today`,void 0),e.r([e.s({type:Array,attribute:`day-strings`})],E.prototype,`dayStrings`,void 0),e.r([e.s({type:Array,attribute:`day-strings-long`})],E.prototype,`dayStringsLong`,void 0),e.r([e.s({type:Array,attribute:`month-strings`})],E.prototype,`monthStrings`,void 0),e.r([e.s({type:String,attribute:`week-string`})],E.prototype,`weekString`,void 0),e.r([e.s({type:String,attribute:`prev-month-string`})],E.prototype,`prevMonthString`,void 0),e.r([e.s({type:String,attribute:`next-month-string`})],E.prototype,`nextMonthString`,void 0),e.r([e.s({type:Array})],E.prototype,`_selected`,void 0),e.r([e.o()],E.prototype,`inRange`,void 0),e.r([e.s({type:Date})],E.prototype,`rangeHovered`,void 0),e.r([e.s({type:Number})],E.prototype,`year`,void 0),e.r([e.s({type:Number})],E.prototype,`month`,void 0),e.r([e.s({type:Number})],E.prototype,`week`,void 0),e.r([e.o()],E.prototype,`currentmonthtouched`,void 0),e.r([e.o()],E.prototype,`focusedDate`,void 0);try{e.c(`pkt-calendar`)(E)}catch{console.warn(`Forsøker å definere <pkt-calendar>, men den er allerede definert`)}var D=E;Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return D}});