@oslokommune/punkt-elements 13.6.11 → 13.6.15

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 (40) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/{combobox-cK_746ek.cjs → combobox-BFOjlFIj.cjs} +1 -1
  3. package/dist/{combobox-DxNotM0u.js → combobox-DaiEdUKx.js} +1 -1
  4. package/dist/datepicker-BR1imflE.cjs +289 -0
  5. package/dist/datepicker-CbVSKaOY.js +1390 -0
  6. package/dist/index.d.ts +125 -7
  7. package/dist/{input-wrapper-D_JdEqcO.js → input-wrapper-CQzXG44g.js} +22 -22
  8. package/dist/{input-wrapper-C9rZEgju.cjs → input-wrapper-DVjNwf8-.cjs} +11 -12
  9. package/dist/pkt-combobox.cjs +1 -1
  10. package/dist/pkt-combobox.js +1 -1
  11. package/dist/pkt-datepicker.cjs +1 -1
  12. package/dist/pkt-datepicker.js +8 -4
  13. package/dist/pkt-index.cjs +1 -1
  14. package/dist/pkt-index.js +6 -6
  15. package/dist/pkt-input-wrapper.cjs +1 -1
  16. package/dist/pkt-input-wrapper.js +1 -1
  17. package/dist/pkt-select.cjs +1 -1
  18. package/dist/pkt-select.js +1 -1
  19. package/dist/pkt-textarea.cjs +1 -1
  20. package/dist/pkt-textarea.js +1 -1
  21. package/dist/pkt-textinput.cjs +1 -1
  22. package/dist/pkt-textinput.js +1 -1
  23. package/dist/{select-D7OQaUrQ.js → select-DKkoxmgj.js} +1 -1
  24. package/dist/{select-Cf1RWSsI.cjs → select-DynzsPo0.cjs} +1 -1
  25. package/dist/{textarea-CXu8UUsY.cjs → textarea-BS1tgktz.cjs} +1 -1
  26. package/dist/{textarea-C0vTWTov.js → textarea-COG1CH_s.js} +1 -1
  27. package/dist/{textinput-C6wccDhZ.cjs → textinput-CCK8ti2y.cjs} +1 -1
  28. package/dist/{textinput-CmZrfH4A.js → textinput-CTOtfcTR.js} +1 -1
  29. package/package.json +3 -3
  30. package/src/components/datepicker/datepicker-multiple.ts +202 -0
  31. package/src/components/datepicker/datepicker-popup.test.ts +77 -0
  32. package/src/components/datepicker/datepicker-popup.ts +137 -0
  33. package/src/components/datepicker/datepicker-range.ts +281 -0
  34. package/src/components/datepicker/datepicker-single.ts +198 -0
  35. package/src/components/datepicker/datepicker-utils.ts +22 -9
  36. package/src/components/datepicker/datepicker.ts +179 -256
  37. package/src/components/datepicker/index.ts +5 -1
  38. package/src/components/input-wrapper/input-wrapper.ts +7 -7
  39. package/dist/datepicker-BEMo4X9s.js +0 -770
  40. package/dist/datepicker-n49TAIAt.cjs +0 -169
@@ -1,5 +1,3 @@
1
- import { classMap } from 'lit/directives/class-map.js'
2
- import { ifDefined } from 'lit/directives/if-defined.js'
3
1
  import { customElement, property, state } from 'lit/decorators.js'
4
2
  import { formatISODate, fromISOToDate, parseISODateString } from '@/utils/dateutils'
5
3
  import { html, nothing, PropertyValues } from 'lit'
@@ -12,19 +10,25 @@ import '@/components/calendar'
12
10
  import '@/components/icon'
13
11
  import '@/components/input-wrapper'
14
12
  import './date-tags'
13
+ import './datepicker-popup'
14
+ import './datepicker-single'
15
+ import './datepicker-range'
16
+ import './datepicker-multiple'
15
17
  import { PktSlotController } from '@/controllers/pkt-slot-controller'
16
- import { keyboardUtils } from './datepicker-utils'
17
18
  import {
18
19
  sleep,
19
20
  deviceDetection,
20
21
  valueUtils,
21
22
  inputTypeUtils,
22
23
  calendarUtils,
23
- eventUtils,
24
24
  cssUtils,
25
25
  dateProcessingUtils,
26
26
  formUtils,
27
27
  } from './datepicker-utils'
28
+ import { PktDatepickerPopup } from './datepicker-popup'
29
+ import { PktDatepickerSingle } from './datepicker-single'
30
+ import { PktDatepickerRange } from './datepicker-range'
31
+ import { PktDatepickerMultiple } from './datepicker-multiple'
28
32
  import { ElementProps } from '@/types/typeUtils'
29
33
 
30
34
  type Props = ElementProps<
@@ -52,8 +56,7 @@ export class PktDatepicker extends PktInputElement<Props> {
52
56
  * Element attributes and properties
53
57
  */
54
58
  private _valueProperty: string = ''
55
- private documentClickListener?: (e: MouseEvent) => void
56
- private documentKeydownListener?: (e: KeyboardEvent) => void
59
+ datepickerPopupRef: Ref<PktDatepickerPopup> = createRef()
57
60
 
58
61
  @property({ type: String, reflect: true })
59
62
  get value(): string {
@@ -116,7 +119,6 @@ export class PktDatepicker extends PktInputElement<Props> {
116
119
  timezone: string = 'Europe/Oslo'
117
120
 
118
121
  @state() inputClasses = {}
119
- @state() buttonClasses = {}
120
122
 
121
123
  /**
122
124
  * Computed properties
@@ -141,30 +143,10 @@ export class PktDatepicker extends PktInputElement<Props> {
141
143
  }
142
144
  this.name =
143
145
  valueUtils.normalizeNameForMultiple(this.name, this.multiple, this.range) || this.name
144
- this.documentClickListener = eventUtils.createDocumentClickListener(
145
- this.inputRef,
146
- this.inputRefTo,
147
- this.btnRef,
148
- () => this.calendarOpen,
149
- this.onBlur.bind(this),
150
- this.hideCalendar.bind(this),
151
- )
152
- this.documentKeydownListener = eventUtils.createDocumentKeydownListener(
153
- () => this.calendarOpen,
154
- this.hideCalendar.bind(this),
155
- )
156
- document.addEventListener('click', this.documentClickListener)
157
- document.addEventListener('keydown', this.documentKeydownListener)
158
146
  }
159
147
 
160
148
  disconnectedCallback(): void {
161
149
  super.disconnectedCallback()
162
- if (this.documentClickListener) {
163
- document.removeEventListener('click', this.documentClickListener)
164
- }
165
- if (this.documentKeydownListener) {
166
- document.removeEventListener('keydown', this.documentKeydownListener)
167
- }
168
150
  }
169
151
 
170
152
  onInput(): void {
@@ -249,253 +231,186 @@ export class PktDatepicker extends PktInputElement<Props> {
249
231
  * Element references
250
232
  */
251
233
 
252
- // When using PktInputElement, we always need to define `inputRef`
253
- inputRef: Ref<HTMLInputElement> = createRef()
254
- inputRefTo: Ref<HTMLInputElement> = createRef()
255
- btnRef: Ref<HTMLButtonElement> = createRef()
234
+ // Override the inputRef and inputRefTo for compatibility
235
+ get inputRef(): Ref<HTMLInputElement> {
236
+ const element = this.currentInputElement
237
+ return { value: element } as Ref<HTMLInputElement>
238
+ }
239
+
240
+ get inputRefTo(): Ref<HTMLInputElement> {
241
+ const element = this.currentInputElementTo
242
+ return { value: element } as Ref<HTMLInputElement>
243
+ }
244
+
256
245
  calRef: Ref<PktCalendar> = createRef()
257
246
  popupRef: Ref<HTMLDivElement> = createRef()
258
247
  helptextSlot: Ref<HTMLElement> = createRef()
259
248
 
249
+ // Child component refs
250
+ singleInputRef: Ref<PktDatepickerSingle> = createRef()
251
+ rangeInputRef: Ref<PktDatepickerRange> = createRef()
252
+ multipleInputRef: Ref<PktDatepickerMultiple> = createRef()
253
+
254
+ // Getters for backward compatibility with input refs
255
+ get currentInputElement(): HTMLInputElement | undefined {
256
+ if (this.multiple) {
257
+ return this.multipleInputRef.value?.inputElement
258
+ } else if (this.range) {
259
+ return this.rangeInputRef.value?.inputElement
260
+ } else {
261
+ return this.singleInputRef.value?.inputElement
262
+ }
263
+ }
264
+
265
+ get currentInputElementTo(): HTMLInputElement | undefined {
266
+ if (this.range) {
267
+ return this.rangeInputRef.value?.inputElementTo
268
+ }
269
+ return undefined
270
+ }
271
+
272
+ get currentButtonElement(): HTMLButtonElement | undefined {
273
+ if (this.multiple) {
274
+ return this.multipleInputRef.value?.buttonElement
275
+ } else if (this.range) {
276
+ return this.rangeInputRef.value?.buttonElement
277
+ } else {
278
+ return this.singleInputRef.value?.buttonElement
279
+ }
280
+ }
281
+
282
+ // Override btnRef for compatibility
283
+ get btnRef(): Ref<HTMLButtonElement> {
284
+ const element = this.currentButtonElement
285
+ return { value: element } as Ref<HTMLButtonElement>
286
+ }
287
+
260
288
  /**
261
289
  * Rendering
262
290
  */
263
291
  renderInput() {
264
292
  return html`
265
- <input
266
- class="${classMap(this.inputClasses)}"
267
- .type=${this.inputType}
268
- id="${this.id}-input"
293
+ <pkt-datepicker-single
269
294
  .value=${this._value[0] ?? ''}
270
- min=${ifDefined(this.min)}
271
- max=${ifDefined(this.max)}
272
- placeholder=${ifDefined(this.placeholder)}
273
- ?readonly=${this.readonly}
274
- aria-describedby="${this.id}-helptext"
275
- @click=${(e: MouseEvent) => {
276
- e.preventDefault()
277
- this.showCalendar()
278
- }}
279
- ?disabled=${this.disabled}
280
- @keydown=${(e: KeyboardEvent) =>
281
- keyboardUtils.handleInputKeydown(
282
- // event, toggleCalendar, submitForm, focusNext, blur, comma
283
- e,
284
- (event) => this.toggleCalendar(event),
285
- () => formUtils.submitFormOrFallback(this.internals, () => this.inputRef.value?.blur()),
286
- undefined,
287
- () => this.inputRef.value?.blur(),
288
- )}
289
- @input=${(e: Event) => {
290
- this.onInput()
291
- e.stopImmediatePropagation()
292
- }}
293
- @focus=${() => {
294
- this.onFocus()
295
- if (deviceDetection.isMobileSafari()) {
296
- this.showCalendar()
297
- }
298
- }}
299
- @blur=${(e: FocusEvent) => {
300
- if (!this.calRef.value?.contains(e.relatedTarget as Node)) {
295
+ .inputType=${this.inputType}
296
+ .id=${this.id}
297
+ .min=${this.min}
298
+ .max=${this.max}
299
+ .placeholder=${this.placeholder}
300
+ .readonly=${this.readonly}
301
+ .disabled=${this.disabled}
302
+ .inputClasses=${this.inputClasses}
303
+ .internals=${this.internals}
304
+ .strings=${this.strings}
305
+ @toggle-calendar=${(e: CustomEvent) => this.toggleCalendar(e.detail)}
306
+ @input-change=${() => this.onInput()}
307
+ @input-focus=${() => this.onFocus()}
308
+ @input-blur=${(e: CustomEvent) => {
309
+ if (!this.calRef.value?.contains(e.detail.relatedTarget as Node)) {
301
310
  this.onBlur()
302
311
  }
303
- this.manageValidity(e.target as HTMLInputElement)
304
- this.value = (e.target as HTMLInputElement).value
305
312
  }}
306
- @change=${(e: Event) => {
313
+ @manage-validity=${(e: CustomEvent) => this.manageValidity(e.detail)}
314
+ @value-change=${(e: CustomEvent) => {
315
+ this.value = e.detail
316
+ }}
317
+ @input-changed=${() => {
307
318
  this.touched = true
308
- e.stopImmediatePropagation()
309
319
  }}
310
- ${ref(this.inputRef)}
311
- />
320
+ ${ref(this.singleInputRef)}
321
+ ></pkt-datepicker-single>
312
322
  `
313
323
  }
314
324
 
315
325
  renderRangeInput() {
316
- const rangeLabelClasses = cssUtils.getRangeLabelClasses(this.showRangeLabels)
317
326
  return html`
318
- ${this.showRangeLabels
319
- ? html` <div class="pkt-input-prefix">${this.strings.generic.from}</div> `
320
- : nothing}
321
- <input
322
- class=${classMap(this.inputClasses)}
323
- .type=${this.inputType}
324
- id="${this.id}-input"
325
- .value=${this._value[0] ?? ''}
326
- min=${ifDefined(this.min)}
327
- max=${ifDefined(this.max)}
328
- placeholder=${ifDefined(this.placeholder)}
329
- ?readonly=${this.readonly}
330
- ?disabled=${this.disabled}
331
- @click=${(e: MouseEvent) => {
332
- e.preventDefault()
333
- this.showCalendar()
334
- }}
335
- @keydown=${(e: KeyboardEvent) =>
336
- keyboardUtils.handleInputKeydown(
337
- // event, toggleCalendar, submitForm, focusNext, blur, comma
338
- e,
339
- (event) => this.toggleCalendar(event),
340
- () =>
341
- formUtils.submitFormOrFallback(this.internals, () => this.inputRefTo.value?.focus()),
342
- () => this.inputRefTo.value?.focus(),
343
- () => this.inputRef.value?.blur(),
344
- )}
345
- @input=${(e: Event) => {
346
- this.onInput()
347
- e.stopImmediatePropagation()
348
- }}
349
- @focus=${() => {
350
- this.onFocus()
351
- if (deviceDetection.isMobileSafari()) {
352
- this.showCalendar()
327
+ <pkt-datepicker-range
328
+ .value=${this._value}
329
+ .inputType=${this.inputType}
330
+ .id=${this.id}
331
+ .min=${this.min}
332
+ .max=${this.max}
333
+ .placeholder=${this.placeholder}
334
+ .readonly=${this.readonly}
335
+ .disabled=${this.disabled}
336
+ .showRangeLabels=${this.showRangeLabels}
337
+ .inputClasses=${this.inputClasses}
338
+ .internals=${this.internals}
339
+ .strings=${this.strings}
340
+ @toggle-calendar=${(e: CustomEvent) => this.toggleCalendar(e.detail)}
341
+ @input-change=${() => this.onInput()}
342
+ @input-focus=${() => this.onFocus()}
343
+ @input-blur=${(e: CustomEvent) => {
344
+ if (!this.calRef.value?.contains(e.detail.relatedTarget as Node)) {
345
+ this.onBlur()
353
346
  }
354
347
  }}
355
- @blur=${(e: Event) => {
348
+ @range-blur=${(e: CustomEvent) => {
356
349
  dateProcessingUtils.processRangeBlur(
357
- e,
358
- this._value,
350
+ e.detail.event,
351
+ e.detail.values,
359
352
  this.calRef,
360
353
  () => this.clearInputValue(),
361
354
  (input) => this.manageValidity(input),
362
355
  )
363
356
  }}
364
- @change=${(e: Event) => {
365
- e.stopImmediatePropagation()
366
- }}
367
- ${ref(this.inputRef)}
368
- />
369
- <div class="${classMap(rangeLabelClasses)}" id="${this.id}-to-label">
370
- ${this.strings.generic.to}
371
- </div>
372
- ${!this.showRangeLabels ? html` <div class="pkt-input-separator">–</div> ` : nothing}
373
- <input
374
- class=${classMap(this.inputClasses)}
375
- .type=${this.inputType}
376
- id="${this.id}-to"
377
- aria-labelledby="${this.id}-to-label"
378
- .value=${this._value[1] ?? ''}
379
- min=${ifDefined(this.min)}
380
- max=${ifDefined(this.max)}
381
- placeholder=${ifDefined(this.placeholder)}
382
- ?readonly=${this.readonly}
383
- ?disabled=${this.disabled}
384
- @click=${(e: MouseEvent) => {
385
- e.preventDefault()
386
- this.showCalendar()
357
+ @manage-validity=${(e: CustomEvent) => this.manageValidity(e.detail)}
358
+ @validate-date-input=${(e: CustomEvent) => {
359
+ formUtils.validateDateInput(e.detail, this.internals, this.min, this.max, this.strings)
387
360
  }}
388
- @keydown=${(e: KeyboardEvent) =>
389
- keyboardUtils.handleInputKeydown(
390
- // event, toggleCalendar, submitForm, focusNext, blur, comma
391
- e,
392
- (event) => this.toggleCalendar(event),
393
- () =>
394
- formUtils.submitFormOrFallback(this.internals, () => this.inputRefTo.value?.blur()),
395
- undefined,
396
- () => this.inputRefTo.value?.blur(),
397
- )}
398
- @input=${(e: Event) => {
399
- this.onInput()
400
- e.stopImmediatePropagation()
401
- }}
402
- @focus=${() => {
403
- this.onFocus()
404
- if (deviceDetection.isMobileSafari()) {
405
- this.showCalendar()
406
- }
407
- }}
408
- @blur=${(e: FocusEvent) => {
409
- if (!this.calRef.value?.contains(e.relatedTarget as Node)) {
410
- this.onBlur()
411
- }
412
- if ((e.target as HTMLInputElement).value) {
413
- this.manageValidity(e.target as HTMLInputElement)
414
- formUtils.validateDateInput(
415
- e.target as HTMLInputElement,
416
- this.internals,
417
- this.min,
418
- this.max,
419
- this.strings,
420
- )
421
- const date = fromISOToDate((e.target as HTMLInputElement).value)
422
- if (date) {
423
- if (this._value[1] !== formatISODate(date)) {
424
- this.calRef?.value?.handleDateSelect(date)
425
- }
361
+ @handle-date-select=${(e: CustomEvent) => {
362
+ const date = fromISOToDate(e.detail)
363
+ if (date) {
364
+ if (this._value[1] !== formatISODate(date)) {
365
+ this.calRef?.value?.handleDateSelect(date)
426
366
  }
427
367
  }
428
368
  }}
429
- @change=${(e: Event) => {
369
+ @input-changed=${() => {
430
370
  this.touched = true
431
- e.stopImmediatePropagation()
432
371
  }}
433
- ${ref(this.inputRefTo)}
434
- />
372
+ ${ref(this.rangeInputRef)}
373
+ ></pkt-datepicker-range>
435
374
  `
436
375
  }
437
376
 
438
377
  renderMultipleInput() {
439
378
  return html`
440
- <input
441
- class=${classMap(this.inputClasses)}
442
- .type=${this.inputType}
443
- id="${this.id}-input"
444
- min=${ifDefined(this.min)}
445
- max=${ifDefined(this.max)}
446
- placeholder=${ifDefined(this.placeholder)}
447
- ?readonly=${this.readonly}
448
- ?disabled=${this.disabled || (this.maxlength && this._value.length >= this.maxlength)}
449
- @click=${(e: MouseEvent) => {
450
- e.preventDefault()
451
- this.showCalendar()
452
- }}
453
- @blur=${(e: FocusEvent) => {
454
- if (!this.calRef.value?.contains(e.relatedTarget as Node)) {
379
+ <pkt-datepicker-multiple
380
+ .value=${this._value}
381
+ .inputType=${this.inputType}
382
+ .id=${this.id}
383
+ .min=${this.min}
384
+ .max=${this.max}
385
+ .placeholder=${this.placeholder}
386
+ .readonly=${this.readonly}
387
+ .disabled=${this.disabled}
388
+ .maxlength=${this.maxlength}
389
+ .inputClasses=${this.inputClasses}
390
+ .internals=${this.internals}
391
+ .strings=${this.strings}
392
+ @toggle-calendar=${(e: CustomEvent) => this.toggleCalendar(e.detail)}
393
+ @input-change=${() => this.onInput()}
394
+ @input-focus=${() => this.onFocus()}
395
+ @input-blur=${(e: CustomEvent) => {
396
+ if (!this.calRef.value?.contains(e.detail.relatedTarget as Node)) {
455
397
  this.onBlur()
456
398
  }
457
- this.addToSelected(e)
458
399
  }}
459
- @input=${(e: Event) => {
460
- this.onInput()
461
- e.stopImmediatePropagation()
462
- }}
463
- @focus=${() => {
464
- this.onFocus()
465
- if (deviceDetection.isMobileSafari()) {
466
- this.showCalendar()
467
- }
468
- }}
469
- @keydown=${(e: KeyboardEvent) =>
470
- keyboardUtils.handleInputKeydown(
471
- // event, toggleCalendar, submitForm, focusNext, blur, comma
472
- e,
473
- (event) => this.toggleCalendar(event),
474
- () => formUtils.submitFormOrFallback(this.internals, () => this.inputRef.value?.blur()),
475
- undefined,
476
- undefined,
477
- (event) => this.addToSelected(event),
478
- )}
479
- @change=${(e: Event) => {
400
+ @add-to-selected=${(e: CustomEvent) => this.addToSelected(e.detail)}
401
+ @input-changed=${() => {
480
402
  this.touched = true
481
- e.stopImmediatePropagation()
482
403
  }}
483
- ${ref(this.inputRef)}
484
- />
404
+ ${ref(this.multipleInputRef)}
405
+ ></pkt-datepicker-multiple>
485
406
  `
486
407
  }
487
408
 
488
409
  renderCalendar() {
489
- return html`<div
490
- class="pkt-calendar-popup pkt-${this.calendarOpen ? 'show' : 'hide'}"
491
- @focusout=${(e: FocusEvent) => {
492
- if (this.calendarOpen) this.handleFocusOut(e)
493
- }}
494
- id="${this.id}-popup"
495
- ${ref(this.popupRef)}
496
- >
497
- <pkt-calendar
498
- id="${this.id}-calendar"
410
+ return html`
411
+ <pkt-datepicker-popup
412
+ class="pkt-contents"
413
+ ?open=${this.calendarOpen}
499
414
  ?multiple=${this.multiple}
500
415
  ?range=${this.range}
501
416
  ?weeknumbers=${this.weeknumbers}
@@ -525,9 +440,9 @@ export class PktDatepicker extends PktInputElement<Props> {
525
440
  this.onBlur()
526
441
  this.hideCalendar()
527
442
  }}
528
- ${ref(this.calRef)}
529
- ></pkt-calendar>
530
- </div>`
443
+ ${ref(this.datepickerPopupRef)}
444
+ ></pkt-datepicker-popup>
445
+ `
531
446
  }
532
447
 
533
448
  render() {
@@ -536,8 +451,9 @@ export class PktDatepicker extends PktInputElement<Props> {
536
451
  this.showRangeLabels,
537
452
  this.multiple,
538
453
  this.range,
454
+ this.readonly,
455
+ this.inputType,
539
456
  )
540
- this.buttonClasses = cssUtils.getButtonClasses()
541
457
 
542
458
  return html`
543
459
  <pkt-input-wrapper
@@ -572,7 +488,13 @@ export class PktDatepicker extends PktInputElement<Props> {
572
488
  strings=${this.strings}
573
489
  id-base=${this.id}
574
490
  @date-tag-removed=${(e: CustomEvent) => {
575
- this.calRef.value?.handleDateSelect(fromISOToDate(e.detail))
491
+ const popup = this.datepickerPopupRef.value
492
+ const date = fromISOToDate(e.detail)
493
+ if (popup && date && typeof popup.handleDateSelect === 'function') {
494
+ popup.handleDateSelect(date)
495
+ } else {
496
+ this.calRef.value?.handleDateSelect(date)
497
+ }
576
498
  }}
577
499
  ></pkt-date-tags>`
578
500
  : nothing}
@@ -581,25 +503,11 @@ export class PktDatepicker extends PktInputElement<Props> {
581
503
  ? 'pkt-input__range-inputs'
582
504
  : ''}"
583
505
  >
584
- <div class="pkt-input__container">
585
- ${this.range
586
- ? this.renderRangeInput()
587
- : this.multiple
588
- ? this.renderMultipleInput()
589
- : this.renderInput()}
590
- <button
591
- class="${classMap(this.buttonClasses)}"
592
- type="button"
593
- @click=${this.toggleCalendar}
594
- @keydown=${(e: KeyboardEvent) =>
595
- keyboardUtils.handleButtonKeydown(e, (event) => this.toggleCalendar(event))}
596
- ?disabled=${this.disabled}
597
- ${ref(this.btnRef)}
598
- >
599
- <pkt-icon name="calendar"></pkt-icon>
600
- <span class="pkt-btn__text">${this.strings.calendar.buttonAltText}</span>
601
- </button>
602
- </div>
506
+ ${this.range
507
+ ? this.renderRangeInput()
508
+ : this.multiple
509
+ ? this.renderMultipleInput()
510
+ : this.renderInput()}
603
511
  </div>
604
512
  </pkt-input-wrapper>
605
513
  ${this.renderCalendar()}
@@ -616,28 +524,43 @@ export class PktDatepicker extends PktInputElement<Props> {
616
524
  }
617
525
 
618
526
  addToSelected = (e: Event | KeyboardEvent) => {
619
- calendarUtils.addToSelected(e, this.calRef, this.min, this.max)
620
- }
621
-
622
- private handleFocusOut(e: FocusEvent) {
623
- eventUtils.handleFocusOut(e, this, this.onBlur.bind(this), this.hideCalendar.bind(this))
527
+ const popup = this.datepickerPopupRef.value
528
+ if (popup && typeof popup.addToSelected === 'function') {
529
+ return popup.addToSelected(e, this.min, this.max)
530
+ }
531
+ return calendarUtils.addToSelected(e, this.calRef, this.min, this.max)
624
532
  }
625
533
 
626
534
  public async showCalendar() {
535
+ const popup = this.datepickerPopupRef.value
627
536
  this.calendarOpen = true
537
+ if (popup && typeof popup.show === 'function') {
538
+ popup.show()
539
+ if (deviceDetection.isIOS()) popup.focusOnCurrentDate()
540
+ return
541
+ }
628
542
  await sleep(20)
629
543
  this.handleCalendarPosition()
630
- if (deviceDetection.isMobileSafari()) {
544
+ if (deviceDetection.isIOS()) {
631
545
  this.calRef.value?.focusOnCurrentDate()
632
546
  }
633
547
  }
634
548
 
635
549
  public hideCalendar() {
550
+ const popup = this.datepickerPopupRef.value
636
551
  this.calendarOpen = false
552
+ if (popup && typeof popup.hide === 'function') return popup.hide()
637
553
  }
638
554
 
639
555
  public async toggleCalendar(e: Event) {
640
556
  e.preventDefault()
557
+ const popup = this.datepickerPopupRef.value
558
+ if (popup && typeof popup.toggle === 'function') {
559
+ const wasOpen = !!popup.open
560
+ popup.toggle()
561
+ this.calendarOpen = !wasOpen
562
+ return
563
+ }
641
564
  this.calendarOpen ? this.hideCalendar() : this.showCalendar()
642
565
  }
643
566
 
@@ -1,3 +1,7 @@
1
1
  import { PktDatepicker } from './datepicker'
2
- export { PktDatepicker }
2
+ import { PktDatepickerSingle } from './datepicker-single'
3
+ import { PktDatepickerRange } from './datepicker-range'
4
+ import { PktDatepickerMultiple } from './datepicker-multiple'
5
+
6
+ export { PktDatepicker, PktDatepickerSingle, PktDatepickerRange, PktDatepickerMultiple }
3
7
  export default PktDatepicker
@@ -11,6 +11,7 @@ import { uuidish } from '@/utils/stringutils'
11
11
  import specs from 'componentSpecs/input-wrapper.json'
12
12
  import '@/components/helptext'
13
13
  import '@/components/icon'
14
+ import '@/components/alert'
14
15
 
15
16
  type TCounterPosition = 'top' | 'bottom'
16
17
  type Props = ElementProps<
@@ -190,16 +191,15 @@ export class PktInputWrapper extends PktElement<Props> {
190
191
 
191
192
  const errorElement = () => {
192
193
  if (this.hasError && this.errorMessage) {
193
- return html`<div
194
- role="alert"
195
- class="pkt-alert pkt-alert--error pkt-alert--compact"
194
+ return html`<pkt-alert
195
+ skin="error"
196
+ compact
197
+ id=${`${this.forId}-error`}
196
198
  aria-live="assertive"
197
199
  aria-atomic="true"
198
- id="${this.forId}-error"
199
200
  >
200
- <pkt-icon name="alert-error" class="pkt-alert__icon"></pkt-icon>
201
- <div class="pkt-alert__text">${unsafeHTML(this.errorMessage)}</div>
202
- </div>`
201
+ ${unsafeHTML(this.errorMessage)}
202
+ </pkt-alert>`
203
203
  } else {
204
204
  return nothing
205
205
  }