@oslokommune/punkt-elements 14.3.0 → 14.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/{checkbox-CnhA52o_.js → checkbox-DfVUNTjH.js} +1 -1
  3. package/dist/{checkbox-C0TPnShf.cjs → checkbox-uxeHrTLH.cjs} +1 -1
  4. package/dist/{combobox-C1xwAju5.cjs → combobox-CcyHcqdW.cjs} +13 -13
  5. package/dist/{combobox-Dcp_fHcL.js → combobox-MZsqmVL-.js} +45 -45
  6. package/dist/{datepicker-COIRRau0.cjs → datepicker-BeMs_vsm.cjs} +25 -25
  7. package/dist/{datepicker-Bjb9GK1E.js → datepicker-a2LvhbRb.js} +215 -234
  8. package/dist/index.d.ts +213 -14
  9. package/dist/input-element-CARcDzQB.js +840 -0
  10. package/dist/input-element-CiaV6jln.cjs +1 -0
  11. package/dist/pkt-checkbox.cjs +1 -1
  12. package/dist/pkt-checkbox.js +1 -1
  13. package/dist/pkt-combobox.cjs +1 -1
  14. package/dist/pkt-combobox.js +1 -1
  15. package/dist/pkt-datepicker.cjs +1 -1
  16. package/dist/pkt-datepicker.js +2 -2
  17. package/dist/pkt-header.cjs +1 -1
  18. package/dist/pkt-header.js +1 -1
  19. package/dist/pkt-index.cjs +1 -1
  20. package/dist/pkt-index.js +7 -7
  21. package/dist/pkt-options-controller-DjBCEHU4.cjs +1 -0
  22. package/dist/{pkt-options-controller-CZO1nxZ8.js → pkt-options-controller-zn5cmMvL.js} +3 -3
  23. package/dist/pkt-radiobutton.cjs +1 -1
  24. package/dist/pkt-radiobutton.js +1 -1
  25. package/dist/pkt-select.cjs +1 -1
  26. package/dist/pkt-select.js +1 -1
  27. package/dist/pkt-textarea.cjs +1 -1
  28. package/dist/pkt-textarea.js +1 -1
  29. package/dist/pkt-textinput.cjs +1 -1
  30. package/dist/pkt-textinput.js +1 -1
  31. package/dist/{radiobutton-Caq8-GhM.js → radiobutton-BmgdSpYf.js} +1 -1
  32. package/dist/{radiobutton-BkqaqO5E.cjs → radiobutton-DVe09YxP.cjs} +1 -1
  33. package/dist/select-7KFOnLln.cjs +49 -0
  34. package/dist/select-CKqz-JKZ.js +228 -0
  35. package/dist/{textarea-a6T4aJJU.js → textarea-Bmrv_vve.js} +1 -1
  36. package/dist/{textarea-DyUy8u7X.cjs → textarea-VBUXPS1O.cjs} +1 -1
  37. package/dist/{textinput-IN3b0nSH.cjs → textinput-BkYKotc1.cjs} +1 -1
  38. package/dist/{textinput-DIuM70dd.js → textinput-Lp1crOmj.js} +1 -1
  39. package/package.json +2 -2
  40. package/src/components/checkbox/checkbox.ts +1 -1
  41. package/src/components/combobox/combobox.ts +2 -2
  42. package/src/components/datepicker/datepicker-utils.test.ts +0 -25
  43. package/src/components/datepicker/datepicker-utils.ts +0 -28
  44. package/src/components/datepicker/datepicker.ts +0 -6
  45. package/src/components/radiobutton/radiobutton.ts +1 -1
  46. package/src/components/select/select.ts +12 -47
  47. package/src/components/textarea/textarea.ts +1 -1
  48. package/src/components/textinput/textinput.ts +1 -1
  49. package/dist/input-element-B8M8Nppd.js +0 -708
  50. package/dist/input-element-D697OAJo.cjs +0 -1
  51. package/dist/pkt-options-controller-CiuBG6Lt.cjs +0 -1
  52. package/dist/select-3dwlk22G.cjs +0 -49
  53. package/dist/select-_C-yztI0.js +0 -173
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oslokommune/punkt-elements",
3
- "version": "14.3.0",
3
+ "version": "14.4.0",
4
4
  "description": "Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo",
5
5
  "homepage": "https://punkt.oslo.kommune.no",
6
6
  "author": "Team Designsystem, Oslo Origo",
@@ -79,5 +79,5 @@
79
79
  "url": "https://github.com/oslokommune/punkt/issues"
80
80
  },
81
81
  "license": "MIT",
82
- "gitHead": "892df7abaa2e9e117dc32b0c44c77592c80233cb"
82
+ "gitHead": "60b409e10bc60371f696d76a84ce6e0d25cb225a"
83
83
  }
@@ -23,7 +23,7 @@ type Props = ElementProps<
23
23
 
24
24
  @customElement('pkt-checkbox')
25
25
  export class PktCheckbox extends PktInputElement<Props> {
26
- private inputRef: Ref<HTMLInputElement> = createRef()
26
+ inputRef: Ref<HTMLInputElement> = createRef()
27
27
 
28
28
  @property({ type: String, reflect: true }) value: string = ''
29
29
  @property({ type: String }) checkHelptext: string | null = null
@@ -93,8 +93,8 @@ export class PktCombobox extends PktInputElement implements IPktCombobox {
93
93
 
94
94
  // State
95
95
  @state() _options: IPktComboboxOption[] = []
96
+ @state() _value: string[] = [] // Internal value representation
96
97
  @state() private _isOptionsOpen = false
97
- @state() private _value: string[] = []
98
98
  @state() private _userInfoMessage: string = ''
99
99
  @state() private _addValueText: string | null = null
100
100
  @state() private _maxIsReached: boolean = false
@@ -130,7 +130,7 @@ export class PktCombobox extends PktInputElement implements IPktCombobox {
130
130
  }
131
131
 
132
132
  // If options are provided via the options slot, we need to extract them
133
- if (this.optionsController.nodes.length) {
133
+ if (this.optionsController?.nodes && this.optionsController.nodes.length) {
134
134
  const options: IPktComboboxOption[] = []
135
135
  this.optionsController.nodes.forEach((node: Element) => {
136
136
  if (!node.textContent && !node.getAttribute('value')) return null
@@ -13,31 +13,6 @@ import { createRef } from 'lit/directives/ref.js'
13
13
 
14
14
  describe('datepicker-utils', () => {
15
15
  describe('valueUtils', () => {
16
- describe('normalizeNameForMultiple', () => {
17
- it('should return null when name is null', () => {
18
- expect(valueUtils.normalizeNameForMultiple(null, false, false)).toBe(null)
19
- expect(valueUtils.normalizeNameForMultiple(null, true, false)).toBe(null)
20
- expect(valueUtils.normalizeNameForMultiple(null, false, true)).toBe(null)
21
- })
22
-
23
- it('should add [] suffix for multiple inputs without []', () => {
24
- expect(valueUtils.normalizeNameForMultiple('dates', true, false)).toBe('dates[]')
25
- })
26
-
27
- it('should add [] suffix for range inputs without []', () => {
28
- expect(valueUtils.normalizeNameForMultiple('daterange', false, true)).toBe('daterange[]')
29
- })
30
-
31
- it('should not add [] suffix when already present', () => {
32
- expect(valueUtils.normalizeNameForMultiple('dates[]', true, false)).toBe('dates[]')
33
- expect(valueUtils.normalizeNameForMultiple('range[]', false, true)).toBe('range[]')
34
- })
35
-
36
- it('should not modify name for single inputs', () => {
37
- expect(valueUtils.normalizeNameForMultiple('singledate', false, false)).toBe('singledate')
38
- })
39
- })
40
-
41
16
  describe('validateRangeOrder', () => {
42
17
  it('should return true for incomplete ranges', () => {
43
18
  expect(valueUtils.validateRangeOrder([])).toBe(true)
@@ -27,34 +27,6 @@ import { PktCalendar } from '@/components/calendar/calendar'
27
27
  * Value parsing and validation utilities
28
28
  */
29
29
  export const valueUtils = {
30
- /**
31
- * Ensures name attribute ends with [] for multiple/range inputs
32
- *
33
- * For form submission to work correctly with multiple values,
34
- * the input name must end with [] to indicate it's an array.
35
- *
36
- * @param name - The original name attribute value
37
- * @param isMultiple - Whether this is a multiple-date picker
38
- * @param isRange - Whether this is a range date picker
39
- * @returns The normalized name with [] suffix if needed, or null if name is null
40
- *
41
- * @example
42
- * normalizeNameForMultiple('dates', true, false) // Returns 'dates[]'
43
- * normalizeNameForMultiple('dates[]', true, false) // Returns 'dates[]' (no change)
44
- * normalizeNameForMultiple('date', false, false) // Returns 'date' (no change)
45
- */
46
- normalizeNameForMultiple(
47
- name: string | null,
48
- isMultiple: boolean,
49
- isRange: boolean,
50
- ): string | null {
51
- if (!name) return null
52
- if ((isMultiple || isRange) && !name.endsWith('[]')) {
53
- return name + '[]'
54
- }
55
- return name
56
- },
57
-
58
30
  /**
59
31
  * Validates that a range has valid order (start <= end)
60
32
  *
@@ -142,8 +142,6 @@ export class PktDatepicker extends PktInputElement<Props> {
142
142
  if (this.timezone && this.timezone !== window.pktTz) {
143
143
  window.pktTz = this.timezone
144
144
  }
145
- this.name =
146
- valueUtils.normalizeNameForMultiple(this.name, this.multiple, this.range) || this.name
147
145
  }
148
146
 
149
147
  disconnectedCallback(): void {
@@ -211,10 +209,6 @@ export class PktDatepicker extends PktInputElement<Props> {
211
209
  const oldValueStr = Array.isArray(oldValue) ? oldValue.join(',') : oldValue
212
210
  this.valueChanged(newValue, oldValueStr)
213
211
  }
214
- if (changedProperties.has('multiple') || changedProperties.has('range')) {
215
- this.name =
216
- valueUtils.normalizeNameForMultiple(this.name, this.multiple, this.range) || this.name
217
- }
218
212
  if (changedProperties.has('multiple')) {
219
213
  if (this.multiple && !Array.isArray(this._value)) {
220
214
  this._value = valueToArray(this.value)
@@ -20,7 +20,7 @@ type Props = ElementProps<
20
20
 
21
21
  @customElement('pkt-radiobutton')
22
22
  export class PktRadioButton extends PktInputElement<Props> {
23
- private inputRef: Ref<HTMLInputElement> = createRef()
23
+ inputRef: Ref<HTMLInputElement> = createRef()
24
24
 
25
25
  @property({ type: String, reflect: true }) value: string = ''
26
26
  @property({ type: String }) checkHelptext: string | null = null
@@ -1,8 +1,8 @@
1
1
  import { html, PropertyValues } from 'lit'
2
- import { customElement, property, state } from 'lit/decorators.js'
2
+ import { customElement, property } from 'lit/decorators.js'
3
3
  import { Ref, createRef, ref } from 'lit/directives/ref.js'
4
4
  import { ifDefined } from 'lit/directives/if-defined.js'
5
- import { PktInputElement } from '@/base-elements/input-element'
5
+ import { PktOptionsInputElement } from '@/base-elements/options-input-element'
6
6
  import { PktOptionsSlotController } from '@/controllers/pkt-options-controller'
7
7
  import { PktSlotController } from '@/controllers/pkt-slot-controller'
8
8
  import '@/components/input-wrapper'
@@ -39,31 +39,15 @@ declare global {
39
39
  }
40
40
 
41
41
  @customElement('pkt-select')
42
- export class PktSelect extends PktInputElement implements IPktSelect {
43
- private inputRef: Ref<HTMLSelectElement> = createRef()
42
+ export class PktSelect extends PktOptionsInputElement<{}, TSelectOption> implements IPktSelect {
43
+ inputRef: Ref<HTMLSelectElement> = createRef()
44
44
  private helptextSlot: Ref<HTMLElement> = createRef()
45
45
 
46
- @property({ type: Array, attribute: 'options' }) private _optionsProp: TSelectOption[] = []
47
46
  @property({ type: String }) value: string = ''
48
47
 
49
- @state() _options: TSelectOption[] = []
50
-
51
48
  public selectedIndex: number | null = -1
52
49
  public selectedOptions: HTMLCollectionOf<HTMLOptionElement> | undefined = undefined
53
50
 
54
- // Getter and setter for options to expose the actual parsed options
55
- public get options(): TSelectOption[] {
56
- return this._options.map((option) => ({
57
- ...option,
58
- selected: option.value === this.value,
59
- }))
60
- }
61
-
62
- public set options(value: TSelectOption[]) {
63
- this._optionsProp = value
64
- this.requestUpdate('_optionsProp', this._options)
65
- }
66
-
67
51
  constructor() {
68
52
  super()
69
53
  this.optionsController = new PktOptionsSlotController(this)
@@ -74,34 +58,15 @@ export class PktSelect extends PktInputElement implements IPktSelect {
74
58
  connectedCallback(): void {
75
59
  super.connectedCallback()
76
60
 
77
- const optionsReceivedFromProps = this._optionsProp.length > 0
78
- const checkIfOptionNodesInSlot =
79
- this.optionsController.nodes.length && this.optionsController.nodes.length > 0
61
+ // Parse options from props or slots
62
+ this.parseOptions()
80
63
 
81
- if (!optionsReceivedFromProps && checkIfOptionNodesInSlot) {
82
- this.optionsController.nodes.forEach((node: Element) => {
83
- const option: TSelectOption = {
84
- value: node.hasAttribute('value')
85
- ? (node.getAttribute('value') ?? '')
86
- : (node.textContent ?? ''),
87
- label: node.textContent || node.getAttribute('value') || '',
88
- disabled: node.hasAttribute('disabled'),
89
- selected: node.hasAttribute('selected'),
90
- hidden: node.hasAttribute('data-hidden'),
91
- }
92
- if (node.getAttribute('selected') && !this.value) {
93
- this.value = option.value
94
- }
95
- this._options.push(option)
96
- })
97
- } else {
98
- this._options = this._optionsProp
99
- this._options.forEach((option) => {
100
- if (option.selected && !this.value) {
101
- this.value = option.value
102
- }
103
- })
104
- }
64
+ // Set initial value from selected option
65
+ this._options.forEach((option) => {
66
+ if (option.selected && !this.value) {
67
+ this.value = option.value
68
+ }
69
+ })
105
70
  }
106
71
 
107
72
  // Support native Select method `add`
@@ -15,7 +15,7 @@ type Props = ElementProps<PktTextarea, 'autocomplete' | 'rows'>
15
15
 
16
16
  @customElement('pkt-textarea')
17
17
  export class PktTextarea extends PktInputElement<Props> {
18
- private inputRef: Ref<HTMLTextAreaElement> = createRef()
18
+ inputRef: Ref<HTMLTextAreaElement> = createRef()
19
19
  private helptextSlot: Ref<HTMLElement> = createRef()
20
20
 
21
21
  @property({ type: String, reflect: true }) value: string = ''
@@ -24,7 +24,7 @@ type Props = ElementProps<
24
24
 
25
25
  @customElement('pkt-textinput')
26
26
  export class PktTextinput extends PktInputElement<Props> {
27
- private inputRef: Ref<HTMLTextAreaElement> = createRef()
27
+ inputRef: Ref<HTMLTextAreaElement> = createRef()
28
28
  private helptextSlot: Ref<HTMLElement> = createRef()
29
29
 
30
30
  @property({ type: String, reflect: true }) value: string = ''