@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.
- package/CHANGELOG.md +34 -0
- package/dist/{combobox-cK_746ek.cjs → combobox-BFOjlFIj.cjs} +1 -1
- package/dist/{combobox-DxNotM0u.js → combobox-DaiEdUKx.js} +1 -1
- package/dist/datepicker-BR1imflE.cjs +289 -0
- package/dist/datepicker-CbVSKaOY.js +1390 -0
- package/dist/index.d.ts +125 -7
- package/dist/{input-wrapper-D_JdEqcO.js → input-wrapper-CQzXG44g.js} +22 -22
- package/dist/{input-wrapper-C9rZEgju.cjs → input-wrapper-DVjNwf8-.cjs} +11 -12
- package/dist/pkt-combobox.cjs +1 -1
- package/dist/pkt-combobox.js +1 -1
- package/dist/pkt-datepicker.cjs +1 -1
- package/dist/pkt-datepicker.js +8 -4
- package/dist/pkt-index.cjs +1 -1
- package/dist/pkt-index.js +6 -6
- package/dist/pkt-input-wrapper.cjs +1 -1
- package/dist/pkt-input-wrapper.js +1 -1
- package/dist/pkt-select.cjs +1 -1
- package/dist/pkt-select.js +1 -1
- package/dist/pkt-textarea.cjs +1 -1
- package/dist/pkt-textarea.js +1 -1
- package/dist/pkt-textinput.cjs +1 -1
- package/dist/pkt-textinput.js +1 -1
- package/dist/{select-D7OQaUrQ.js → select-DKkoxmgj.js} +1 -1
- package/dist/{select-Cf1RWSsI.cjs → select-DynzsPo0.cjs} +1 -1
- package/dist/{textarea-CXu8UUsY.cjs → textarea-BS1tgktz.cjs} +1 -1
- package/dist/{textarea-C0vTWTov.js → textarea-COG1CH_s.js} +1 -1
- package/dist/{textinput-C6wccDhZ.cjs → textinput-CCK8ti2y.cjs} +1 -1
- package/dist/{textinput-CmZrfH4A.js → textinput-CTOtfcTR.js} +1 -1
- package/package.json +3 -3
- package/src/components/datepicker/datepicker-multiple.ts +202 -0
- package/src/components/datepicker/datepicker-popup.test.ts +77 -0
- package/src/components/datepicker/datepicker-popup.ts +137 -0
- package/src/components/datepicker/datepicker-range.ts +281 -0
- package/src/components/datepicker/datepicker-single.ts +198 -0
- package/src/components/datepicker/datepicker-utils.ts +22 -9
- package/src/components/datepicker/datepicker.ts +179 -256
- package/src/components/datepicker/index.ts +5 -1
- package/src/components/input-wrapper/input-wrapper.ts +7 -7
- package/dist/datepicker-BEMo4X9s.js +0 -770
- package/dist/datepicker-n49TAIAt.cjs +0 -169
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { html } from 'lit'
|
|
2
|
+
import { customElement, property } from 'lit/decorators.js'
|
|
3
|
+
import { classMap } from 'lit/directives/class-map.js'
|
|
4
|
+
import { ifDefined } from 'lit/directives/if-defined.js'
|
|
5
|
+
import { Ref, createRef, ref } from 'lit/directives/ref.js'
|
|
6
|
+
import { PktElement } from '@/base-elements/element'
|
|
7
|
+
import { keyboardUtils, formUtils, deviceDetection, cssUtils } from './datepicker-utils'
|
|
8
|
+
import '@/components/icon'
|
|
9
|
+
|
|
10
|
+
@customElement('pkt-datepicker-single')
|
|
11
|
+
export class PktDatepickerSingle extends PktElement {
|
|
12
|
+
@property({ type: String })
|
|
13
|
+
value: string = ''
|
|
14
|
+
|
|
15
|
+
@property({ type: String })
|
|
16
|
+
inputType: string = 'date'
|
|
17
|
+
|
|
18
|
+
@property({ type: String })
|
|
19
|
+
id: string = ''
|
|
20
|
+
|
|
21
|
+
@property({ type: String })
|
|
22
|
+
min?: string
|
|
23
|
+
|
|
24
|
+
@property({ type: String })
|
|
25
|
+
max?: string
|
|
26
|
+
|
|
27
|
+
@property({ type: String })
|
|
28
|
+
placeholder?: string
|
|
29
|
+
|
|
30
|
+
@property({ type: Boolean })
|
|
31
|
+
readonly: boolean = false
|
|
32
|
+
|
|
33
|
+
@property({ type: Boolean })
|
|
34
|
+
disabled: boolean = false
|
|
35
|
+
|
|
36
|
+
@property({ type: Object })
|
|
37
|
+
inputClasses: Record<string, boolean> = {}
|
|
38
|
+
|
|
39
|
+
@property({ type: Object })
|
|
40
|
+
internals?: any
|
|
41
|
+
|
|
42
|
+
@property({ type: Object })
|
|
43
|
+
strings: any = { calendar: { buttonAltText: 'Åpne kalender' } }
|
|
44
|
+
|
|
45
|
+
inputRef: Ref<HTMLInputElement> = createRef()
|
|
46
|
+
btnRef: Ref<HTMLButtonElement> = createRef()
|
|
47
|
+
|
|
48
|
+
get inputElement(): HTMLInputElement | undefined {
|
|
49
|
+
return this.inputRef.value
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get buttonElement(): HTMLButtonElement | undefined {
|
|
53
|
+
return this.btnRef.value
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get isInputReadonly(): boolean {
|
|
57
|
+
return this.readonly || this.inputType === 'text'
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private dispatchToggleCalendar(e: Event) {
|
|
61
|
+
if (this.readonly) return
|
|
62
|
+
|
|
63
|
+
this.dispatchEvent(
|
|
64
|
+
new CustomEvent('toggle-calendar', {
|
|
65
|
+
detail: e,
|
|
66
|
+
bubbles: true,
|
|
67
|
+
composed: true,
|
|
68
|
+
}),
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private dispatchInput(e: Event) {
|
|
73
|
+
this.dispatchEvent(
|
|
74
|
+
new CustomEvent('input-change', {
|
|
75
|
+
detail: e,
|
|
76
|
+
bubbles: true,
|
|
77
|
+
composed: true,
|
|
78
|
+
}),
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private dispatchFocus() {
|
|
83
|
+
this.dispatchEvent(
|
|
84
|
+
new CustomEvent('input-focus', {
|
|
85
|
+
bubbles: true,
|
|
86
|
+
composed: true,
|
|
87
|
+
}),
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private dispatchBlur(e: FocusEvent) {
|
|
92
|
+
this.dispatchEvent(
|
|
93
|
+
new CustomEvent('input-blur', {
|
|
94
|
+
detail: e,
|
|
95
|
+
bubbles: true,
|
|
96
|
+
composed: true,
|
|
97
|
+
}),
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private dispatchChange(e: Event) {
|
|
102
|
+
this.dispatchEvent(
|
|
103
|
+
new CustomEvent('input-changed', {
|
|
104
|
+
detail: e,
|
|
105
|
+
bubbles: true,
|
|
106
|
+
composed: true,
|
|
107
|
+
}),
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private dispatchManageValidity(input: HTMLInputElement) {
|
|
112
|
+
this.dispatchEvent(
|
|
113
|
+
new CustomEvent('manage-validity', {
|
|
114
|
+
detail: input,
|
|
115
|
+
bubbles: true,
|
|
116
|
+
composed: true,
|
|
117
|
+
}),
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
createRenderRoot() {
|
|
122
|
+
return this
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
render() {
|
|
126
|
+
return html`
|
|
127
|
+
<div class="pkt-input__container">
|
|
128
|
+
<input
|
|
129
|
+
class="${classMap(this.inputClasses)}"
|
|
130
|
+
.type=${this.inputType}
|
|
131
|
+
id="${this.id}-input"
|
|
132
|
+
.value=${this.value}
|
|
133
|
+
min=${ifDefined(this.min)}
|
|
134
|
+
max=${ifDefined(this.max)}
|
|
135
|
+
placeholder=${ifDefined(this.placeholder)}
|
|
136
|
+
?readonly=${this.isInputReadonly}
|
|
137
|
+
aria-describedby="${this.id}-helptext"
|
|
138
|
+
@click=${(e: MouseEvent) => {
|
|
139
|
+
e.preventDefault()
|
|
140
|
+
this.dispatchToggleCalendar(e)
|
|
141
|
+
}}
|
|
142
|
+
@touchend=${(e: TouchEvent) => {
|
|
143
|
+
e.preventDefault()
|
|
144
|
+
this.dispatchToggleCalendar(e)
|
|
145
|
+
}}
|
|
146
|
+
?disabled=${this.disabled}
|
|
147
|
+
@keydown=${(e: KeyboardEvent) =>
|
|
148
|
+
keyboardUtils.handleInputKeydown(
|
|
149
|
+
e,
|
|
150
|
+
(event) => this.dispatchToggleCalendar(event),
|
|
151
|
+
() =>
|
|
152
|
+
formUtils.submitFormOrFallback(this.internals, () => this.inputRef.value?.blur()),
|
|
153
|
+
undefined,
|
|
154
|
+
() => this.inputRef.value?.blur(),
|
|
155
|
+
)}
|
|
156
|
+
@input=${(e: Event) => {
|
|
157
|
+
this.dispatchInput(e)
|
|
158
|
+
e.stopImmediatePropagation()
|
|
159
|
+
}}
|
|
160
|
+
@focus=${() => {
|
|
161
|
+
this.dispatchFocus()
|
|
162
|
+
if (deviceDetection.isIOS()) {
|
|
163
|
+
this.dispatchToggleCalendar(new Event('focus'))
|
|
164
|
+
}
|
|
165
|
+
}}
|
|
166
|
+
@blur=${(e: FocusEvent) => {
|
|
167
|
+
this.dispatchBlur(e)
|
|
168
|
+
this.dispatchManageValidity(e.target as HTMLInputElement)
|
|
169
|
+
this.dispatchEvent(
|
|
170
|
+
new CustomEvent('value-change', {
|
|
171
|
+
detail: (e.target as HTMLInputElement).value,
|
|
172
|
+
bubbles: true,
|
|
173
|
+
composed: true,
|
|
174
|
+
}),
|
|
175
|
+
)
|
|
176
|
+
}}
|
|
177
|
+
@change=${(e: Event) => {
|
|
178
|
+
this.dispatchChange(e)
|
|
179
|
+
e.stopImmediatePropagation()
|
|
180
|
+
}}
|
|
181
|
+
${ref(this.inputRef)}
|
|
182
|
+
/>
|
|
183
|
+
<button
|
|
184
|
+
class="${classMap(cssUtils.getButtonClasses())}"
|
|
185
|
+
type="button"
|
|
186
|
+
@click=${(e: Event) => this.dispatchToggleCalendar(e)}
|
|
187
|
+
@keydown=${(e: KeyboardEvent) =>
|
|
188
|
+
keyboardUtils.handleButtonKeydown(e, (event) => this.dispatchToggleCalendar(event))}
|
|
189
|
+
?disabled=${this.disabled}
|
|
190
|
+
${ref(this.btnRef)}
|
|
191
|
+
>
|
|
192
|
+
<pkt-icon name="calendar"></pkt-icon>
|
|
193
|
+
<span class="pkt-btn__text">${this.strings.calendar.buttonAltText}</span>
|
|
194
|
+
</button>
|
|
195
|
+
</div>
|
|
196
|
+
`
|
|
197
|
+
}
|
|
198
|
+
}
|
|
@@ -24,18 +24,23 @@ export const sleep = (ms: number): Promise<void> =>
|
|
|
24
24
|
export const deviceDetection = {
|
|
25
25
|
/**
|
|
26
26
|
* Detects if the current device is iOS (iPhone, iPad, iPod)
|
|
27
|
+
* Handles modern iPad Safari which uses desktop user agent since iOS 13
|
|
27
28
|
*/
|
|
28
29
|
isIOS(): boolean {
|
|
29
30
|
const ua = navigator.userAgent
|
|
30
|
-
return /iP(hone|od|ad)/.test(ua)
|
|
31
|
-
},
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
// Legacy iOS detection (iPhone, iPod, older iPads)
|
|
33
|
+
if (/iP(hone|od|ad)/.test(ua)) {
|
|
34
|
+
return true
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Modern iPad detection (iOS 13+ iPads identify as Mac)
|
|
38
|
+
// Check for Mac + touch support
|
|
39
|
+
if (/Macintosh/.test(ua) && 'ontouchend' in document) {
|
|
40
|
+
return true
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return false
|
|
39
44
|
},
|
|
40
45
|
}
|
|
41
46
|
|
|
@@ -317,7 +322,14 @@ export const cssUtils = {
|
|
|
317
322
|
/**
|
|
318
323
|
* Generates input classes for datepicker
|
|
319
324
|
*/
|
|
320
|
-
getInputClasses(
|
|
325
|
+
getInputClasses(
|
|
326
|
+
fullwidth: boolean,
|
|
327
|
+
showRangeLabels: boolean,
|
|
328
|
+
multiple: boolean,
|
|
329
|
+
range: boolean,
|
|
330
|
+
readonly?: boolean,
|
|
331
|
+
inputType?: string
|
|
332
|
+
) {
|
|
321
333
|
return {
|
|
322
334
|
'pkt-input': true,
|
|
323
335
|
'pkt-datepicker__input': true,
|
|
@@ -325,6 +337,7 @@ export const cssUtils = {
|
|
|
325
337
|
'pkt-datepicker--hasrangelabels': showRangeLabels,
|
|
326
338
|
'pkt-datepicker--multiple': multiple,
|
|
327
339
|
'pkt-datepicker--range': range,
|
|
340
|
+
'ios-readonly-hack': readonly === false && inputType === 'text',
|
|
328
341
|
}
|
|
329
342
|
},
|
|
330
343
|
|