@oslokommune/punkt-elements 19.6.0 → 19.8.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 (68) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/{alert-IaZzEgyI.cjs → alert-CKqtC9AM.cjs} +1 -1
  3. package/dist/{alert-C0PiYnot.js → alert-WME3geaX.js} +5 -0
  4. package/dist/base-elements/input-element.d.ts +1 -0
  5. package/dist/combobox-89Ohd1Oe.cjs +139 -0
  6. package/dist/{combobox-CWzWHBaw.js → combobox-Cpb67TV0.js} +47 -423
  7. package/dist/components/combobox/combobox-base.d.ts +2 -2
  8. package/dist/components/combobox/combobox.d.ts +9 -26
  9. package/dist/components/input-wrapper/input-wrapper.d.ts +1 -0
  10. package/dist/components/messagebox/messagebox.d.ts +2 -6
  11. package/dist/{datepicker-CWHYYj-H.cjs → datepicker-B9NCJX4o.cjs} +1 -1
  12. package/dist/{datepicker-Bs7Z3EFn.js → datepicker-DBEKa1aJ.js} +1 -1
  13. package/dist/{fileupload-CMIFZWJ5.cjs → fileupload-2YAbjYuU.cjs} +1 -1
  14. package/dist/{fileupload-BQFJx1ok.js → fileupload-DqWCXMPz.js} +2 -2
  15. package/dist/{header-C4Uojzoy.cjs → header-9Y6Q6Cfq.cjs} +1 -1
  16. package/dist/{header-Cc1Cy0U3.js → header-Dp0Lq7wS.js} +1 -1
  17. package/dist/{input-wrapper-BoTugCvh.js → input-wrapper-C9K-_7g-.js} +1 -1
  18. package/dist/{input-wrapper-J3mEKhvR.cjs → input-wrapper-CTMf4kCK.cjs} +1 -1
  19. package/dist/{messagebox-DPFBuisE.js → messagebox-D17GYxb9.js} +5 -45
  20. package/dist/messagebox-X01V2l_N.cjs +13 -0
  21. package/dist/pkt-alert.cjs +1 -1
  22. package/dist/pkt-alert.js +1 -1
  23. package/dist/pkt-combobox.cjs +1 -1
  24. package/dist/pkt-combobox.js +1 -1
  25. package/dist/pkt-datepicker.cjs +1 -1
  26. package/dist/pkt-datepicker.js +1 -1
  27. package/dist/pkt-fileupload.cjs +1 -1
  28. package/dist/pkt-fileupload.js +1 -1
  29. package/dist/pkt-header.cjs +1 -1
  30. package/dist/pkt-header.js +1 -1
  31. package/dist/pkt-index.cjs +1 -1
  32. package/dist/pkt-index.js +28 -28
  33. package/dist/pkt-input-wrapper.cjs +1 -1
  34. package/dist/pkt-input-wrapper.js +1 -1
  35. package/dist/pkt-messagebox.cjs +1 -1
  36. package/dist/pkt-messagebox.js +1 -1
  37. package/dist/pkt-select.cjs +1 -1
  38. package/dist/pkt-select.js +1 -1
  39. package/dist/pkt-textarea.cjs +1 -1
  40. package/dist/pkt-textarea.js +1 -1
  41. package/dist/pkt-textinput.cjs +1 -1
  42. package/dist/pkt-textinput.js +1 -1
  43. package/dist/pkt-timepicker.cjs +1 -1
  44. package/dist/pkt-timepicker.js +1 -1
  45. package/dist/{select-CZYQ5Dmx.cjs → select-CZk57p1_.cjs} +1 -1
  46. package/dist/{select-DYjKMmHa.js → select-Cz80KV3g.js} +1 -1
  47. package/dist/shared-types/combobox.d.ts +73 -5
  48. package/dist/shared-types/index.d.ts +6 -2
  49. package/dist/shared-types/messagebox.d.ts +32 -0
  50. package/dist/shared-types/size.d.ts +3 -3
  51. package/dist/shared-types/skin.d.ts +1 -4
  52. package/dist/{textarea-C2oaRlfb.js → textarea-Dfvx1I60.js} +1 -1
  53. package/dist/{textarea-H1Lt2o6K.cjs → textarea-Dwjx-Crl.cjs} +1 -1
  54. package/dist/{textinput-C0eu70sH.js → textinput-7zTPlXVj.js} +1 -1
  55. package/dist/{textinput-C2Tx-OrN.cjs → textinput-BeraGRzb.cjs} +1 -1
  56. package/dist/{timepicker-B8TwchA2.js → timepicker-C0dSH4Ij.js} +1 -1
  57. package/dist/{timepicker-DZG_gHIa.cjs → timepicker-DarB9eA6.cjs} +1 -1
  58. package/package.json +2 -2
  59. package/src/components/alert/alert.ts +1 -1
  60. package/src/components/combobox/combobox-base.ts +14 -8
  61. package/src/components/combobox/combobox-value.ts +2 -2
  62. package/src/components/combobox/combobox.attributes.test.ts +3 -2
  63. package/src/components/combobox/combobox.ts +26 -26
  64. package/src/components/input-wrapper/input-wrapper.ts +1 -0
  65. package/src/components/messagebox/messagebox.test.ts +1 -1
  66. package/src/components/messagebox/messagebox.ts +6 -12
  67. package/dist/combobox-FCguoyDH.cjs +0 -139
  68. package/dist/messagebox-JWKMJEFc.cjs +0 -13
@@ -2,14 +2,17 @@
2
2
  * combobox.ts
3
3
  *
4
4
  * Type definitions for the combobox and listbox components.
5
- * Used by both Elements and React implementations
6
- * and by the shared combobox helper functions.
5
+ * Used by both Elements and React implementations,
6
+ * the shared combobox helper functions, and typed component specs.
7
7
  */
8
+ import type { IFormFieldErrorProps, IFormFieldLabelProps, IHelptextProps, ITagOptionalRequiredProps } from './form-field';
9
+ import type { TPktInputSize } from './size';
8
10
  /**
9
11
  * Tag skin colors available for combobox option tags.
10
12
  * Matches the TTagSkin values from the tag component.
11
13
  */
12
- export type TPktComboboxTagSkin = 'blue' | 'blue-dark' | 'blue-light' | 'green' | 'red' | 'yellow' | 'beige' | 'gray' | 'grey';
14
+ export declare const COMBOBOX_TAG_SKINS: readonly ['blue', 'blue-dark', 'blue-light', 'green', 'red', 'yellow', 'beige', 'gray', 'grey'];
15
+ export type TPktComboboxTagSkin = (typeof COMBOBOX_TAG_SKINS)[number];
13
16
  /**
14
17
  * Represents a single option in a combobox or listbox.
15
18
  */
@@ -27,8 +30,73 @@ export interface IPktComboboxOption {
27
30
  /**
28
31
  * How the selected value is displayed in the combobox input.
29
32
  */
30
- export type TPktComboboxDisplayValue = 'label' | 'value' | 'prefixAndValue';
33
+ export declare const COMBOBOX_DISPLAY_VALUES: readonly ['label', 'value', 'prefixAndValue'];
34
+ export type TPktComboboxDisplayValue = (typeof COMBOBOX_DISPLAY_VALUES)[number];
31
35
  /**
32
36
  * Placement of selected value tags in multiple selection mode.
33
37
  */
34
- export type TPktComboboxTagPlacement = 'inside' | 'outside';
38
+ export declare const COMBOBOX_TAG_PLACEMENTS: readonly ['inside', 'outside'];
39
+ export type TPktComboboxTagPlacement = (typeof COMBOBOX_TAG_PLACEMENTS)[number];
40
+ /**
41
+ * Combobox props shared by React, Elements, and typed component specs.
42
+ *
43
+ * @remarks Both frameworks extend this with `Omit<>` and widen a few props:
44
+ * - React widens `helptext`, `helptextDropdown` and `errorMessage` to `ReactNode`.
45
+ * - Elements widens string/number props to `| null` (Lit uses `null` for an unset attribute,
46
+ * see `PktInputElement`) and `useWrapper` to `Booleanish`. Elements omits `form`, which is
47
+ * a getter returning the associated `HTMLFormElement`, not the form id.
48
+ *
49
+ * `hasFieldset` and `counter` are tri-state: `null` means the component derives the value.
50
+ */
51
+ export interface IPktComboboxBase extends IFormFieldLabelProps, IHelptextProps, IFormFieldErrorProps, ITagOptionalRequiredProps {
52
+ id?: string;
53
+ name?: string;
54
+ form?: string;
55
+ ariaDescribedby?: string;
56
+ placeholder?: string;
57
+ required?: boolean;
58
+ value?: string | string[];
59
+ defaultValue?: string | string[];
60
+ options?: IPktComboboxOption[];
61
+ defaultOptions?: IPktComboboxOption[];
62
+ multiple?: boolean;
63
+ maxlength?: number;
64
+ typeahead?: boolean;
65
+ includeSearch?: boolean;
66
+ allowUserInput?: boolean;
67
+ searchPlaceholder?: string;
68
+ displayValueAs?: TPktComboboxDisplayValue;
69
+ tagPlacement?: TPktComboboxTagPlacement;
70
+ inputSize?: TPktInputSize;
71
+ fullwidth?: boolean;
72
+ inline?: boolean;
73
+ useWrapper?: boolean;
74
+ hasFieldset?: boolean | null;
75
+ counter?: boolean | null;
76
+ }
77
+ /**
78
+ * Documented Combobox props (subset of `IPktComboboxBase`).
79
+ * Used for typed component specs in documentation.
80
+ */
81
+ export type IComboboxSpecProps = Pick<IPktComboboxBase, 'name' | 'form' | 'ariaDescribedby' | 'id' | 'label' | 'placeholder' | 'multiple' | 'tagPlacement' | 'maxlength' | 'typeahead' | 'includeSearch' | 'allowUserInput' | 'searchPlaceholder' | 'displayValueAs' | 'inputSize' | 'value' | 'helptext' | 'helptextDropdown' | 'helptextDropdownButton' | 'disabled' | 'hasError' | 'errorMessage' | 'required' | 'requiredTag' | 'requiredText' | 'optionalTag' | 'optionalText' | 'tagText' | 'fullwidth' | 'defaultOptions' | 'options' | 'inline' | 'useWrapper' | 'hasFieldset' | 'counter' | 'defaultValue'>;
82
+ /**
83
+ * Default values for pkt-combobox. Single source of truth for both frameworks.
84
+ * Array defaults (`options`, `defaultOptions`) are intentionally absent — a shared array
85
+ * instance would be mutated across component instances.
86
+ */
87
+ export declare const COMBOBOX_DEFAULTS: {
88
+ readonly multiple: false;
89
+ readonly typeahead: false;
90
+ readonly includeSearch: false;
91
+ readonly allowUserInput: false;
92
+ readonly displayValueAs: 'label';
93
+ readonly inputSize: 'medium';
94
+ readonly disabled: false;
95
+ readonly hasError: false;
96
+ readonly required: false;
97
+ readonly requiredTag: false;
98
+ readonly optionalTag: false;
99
+ readonly fullwidth: false;
100
+ readonly inline: false;
101
+ readonly useWrapper: true;
102
+ };
@@ -20,6 +20,7 @@ export type { TIconSizeClass, IPktIconBase, IIconSpecProps } from './icon';
20
20
  export { LAYOUT_DIRECTIONS } from './layout';
21
21
  export type { TLayout, TVerticalPosition, THorizontalPosition, TPosition, TPositionWithCenter, } from './layout';
22
22
  export type { THTMLButtonType, TSelectionMode } from './form';
23
+ export { INPUT_SIZES } from './size';
23
24
  export type { TPktInputSize, TSize3, TSize5, TSize7 } from './size';
24
25
  export { ACCORDION_SKINS } from './accordion';
25
26
  export type { TAccordionSkin, IPktAccordionBase, IPktAccordionItemBase, IAccordionSpecProps, IAccordionItemSpecProps, IAccordionVisualProps, } from './accordion';
@@ -33,7 +34,9 @@ export type { TBreadcrumbsNavigationType, IBreadcrumb, IBreadcrumbItem, IBreadcr
33
34
  export type { IRenderLink, TRenderLink } from './render-link';
34
35
  export type { IPktStringsProps } from '../shared-strings';
35
36
  export type { IHelptextProps, ITagOptionalRequiredProps, IFormFieldLabelProps, IFormFieldErrorProps, IFormFieldCommonProps, TFormFieldCommonSpecKeys, } from './form-field';
36
- export type { TMessageboxSkin, TTagSkin } from './skin';
37
+ export type { TTagSkin } from './skin';
38
+ export { MESSAGEBOX_SKINS, MESSAGEBOX_DEFAULTS } from './messagebox';
39
+ export type { TMessageboxSkin, IPktMessageboxBase, IMessageboxSpecProps } from './messagebox';
37
40
  export { CALENDAR_DEFAULTS } from './calendar';
38
41
  export type { IPktCalendarBase, ICalendarSpecProps, IDateConstraints, ICalendarGridDimensions, IGridCellPosition, TDateRangeMap, ISelectionState, ISelectionOptions, } from './calendar';
39
42
  export type { IDatepickerStrings } from './datepicker';
@@ -41,7 +44,8 @@ export { defaultSingleStrings, defaultRangeStrings } from './datepicker';
41
44
  export type { ITimepickerStrings } from './timepicker';
42
45
  export { defaultTimepickerStrings } from './timepicker';
43
46
  export type { TProgressbarRole, TProgressbarSkin, TProgressbarStatusPlacement, TProgressbarStatusType, TProgressbarTitlePosition, } from './progressbar';
44
- export type { IPktComboboxOption, TPktComboboxTagSkin, TPktComboboxDisplayValue, TPktComboboxTagPlacement, } from './combobox';
47
+ export { COMBOBOX_TAG_SKINS, COMBOBOX_DISPLAY_VALUES, COMBOBOX_TAG_PLACEMENTS, COMBOBOX_DEFAULTS, } from './combobox';
48
+ export type { IPktComboboxOption, TPktComboboxTagSkin, TPktComboboxDisplayValue, TPktComboboxTagPlacement, IPktComboboxBase, IComboboxSpecProps, } from './combobox';
45
49
  export type { IPktSelectOption, TSelectOption } from './select';
46
50
  export type { TPktSearchInputAppearance, TPktSearchInputMethod, IPktSearchInputSuggestion, IPktSearchInput, } from './searchinput';
47
51
  export { UPLOAD_STRATEGIES, FILE_UPLOAD_ITEM_RENDERERS, PREVIEW_UPLOAD_STATUS, } from './fileupload';
@@ -0,0 +1,32 @@
1
+ /**
2
+ * messagebox.ts
3
+ *
4
+ * Type definitions for pkt-messagebox.
5
+ * Used by React, Elements, and typed component specs.
6
+ */
7
+ /** Messagebox skin variants — shared runtime source for types, specs, and Preview. */
8
+ export declare const MESSAGEBOX_SKINS: readonly ['beige', 'blue', 'red', 'green'];
9
+ export type TMessageboxSkin = (typeof MESSAGEBOX_SKINS)[number];
10
+ /**
11
+ * Messagebox props shared by React and Elements.
12
+ *
13
+ * @remarks React widens `title` to `ReactNode` and adds `onClose`.
14
+ * Elements dispatches a `close` event instead (and `on-close` for legacy Vue setups).
15
+ */
16
+ export interface IPktMessageboxBase {
17
+ skin?: TMessageboxSkin;
18
+ title?: string;
19
+ compact?: boolean;
20
+ closable?: boolean;
21
+ }
22
+ /**
23
+ * Documented Messagebox props (subset of `IPktMessageboxBase`).
24
+ * Used for typed component specs in documentation.
25
+ */
26
+ export type IMessageboxSpecProps = Pick<IPktMessageboxBase, 'title' | 'skin' | 'compact' | 'closable'>;
27
+ /** Default values for pkt-messagebox. Single source of truth for both frameworks. */
28
+ export declare const MESSAGEBOX_DEFAULTS: {
29
+ readonly skin: 'beige';
30
+ readonly compact: false;
31
+ readonly closable: false;
32
+ };
@@ -17,7 +17,7 @@ export type TSize5 = 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
17
17
  */
18
18
  export type TSize7 = 'xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge';
19
19
  /**
20
- * Sizes used in our input components
20
+ * Sizes used in our input components — shared runtime source for types, specs, and Preview.
21
21
  */
22
- export declare const InputSize: readonly ['xsmall', 'small', 'medium'];
23
- export type TPktInputSize = (typeof InputSize)[number];
22
+ export declare const INPUT_SIZES: readonly ['xsmall', 'small', 'medium'];
23
+ export type TPktInputSize = (typeof INPUT_SIZES)[number];
@@ -8,10 +8,7 @@
8
8
  export { ALERT_SKINS, type TAlertSkin } from './alert';
9
9
  export { ACCORDION_SKINS, type TAccordionSkin } from './accordion';
10
10
  export { CARD_SKINS, type TCardSkin } from './card';
11
- /**
12
- * Messagebox component skin variants
13
- */
14
- export type TMessageboxSkin = 'beige' | 'blue' | 'red' | 'green';
11
+ export { MESSAGEBOX_SKINS, type TMessageboxSkin } from './messagebox';
15
12
  /**
16
13
  * Tag component skin variants
17
14
  */
@@ -6,7 +6,7 @@ import "./icon-JigbxxF7.js";
6
6
  import { t as m } from "./if-defined-Bebu3LXY.js";
7
7
  import { n as h, t as g } from "./ref-CCSGk4MP.js";
8
8
  import { t as _ } from "./input-element-lLzfwdim.js";
9
- import { r as v } from "./input-wrapper-BoTugCvh.js";
9
+ import { r as v } from "./input-wrapper-C9K-_7g-.js";
10
10
  //#region ../../node_modules/lit-html/directives/live.js
11
11
  var y = n(class extends c {
12
12
  constructor(e) {
@@ -1,4 +1,4 @@
1
- const e=require("./element-BOmr9YLv.cjs"),t=require("./class-map-Drv0_anQ.cjs"),n=require("./directive-helpers-BRrz3Bcj.cjs"),r=require("./element-with-slot-D7sTqOr3.cjs");require("./icon-Dnv6LtPC.cjs");const i=require("./if-defined-2mkIDgOm.cjs"),a=require("./ref-Emu5PNxk.cjs"),o=require("./input-element-CSfDGslx.cjs"),s=require("./input-wrapper-J3mEKhvR.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-BOmr9YLv.cjs"),t=require("./class-map-Drv0_anQ.cjs"),n=require("./directive-helpers-BRrz3Bcj.cjs"),r=require("./element-with-slot-D7sTqOr3.cjs");require("./icon-Dnv6LtPC.cjs");const i=require("./if-defined-2mkIDgOm.cjs"),a=require("./ref-Emu5PNxk.cjs"),o=require("./input-element-CSfDGslx.cjs"),s=require("./input-wrapper-CTMf4kCK.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}
@@ -5,7 +5,7 @@ import "./icon-JigbxxF7.js";
5
5
  import { t as c } from "./if-defined-Bebu3LXY.js";
6
6
  import { n as l, t as u } from "./ref-CCSGk4MP.js";
7
7
  import { t as d } from "./input-element-lLzfwdim.js";
8
- import { r as f } from "./input-wrapper-BoTugCvh.js";
8
+ import { r as f } from "./input-wrapper-C9K-_7g-.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-BOmr9YLv.cjs"),t=require("./class-map-Drv0_anQ.cjs"),n=require("./element-with-slot-D7sTqOr3.cjs");require("./icon-Dnv6LtPC.cjs");const r=require("./if-defined-2mkIDgOm.cjs"),i=require("./ref-Emu5PNxk.cjs"),a=require("./input-element-CSfDGslx.cjs"),o=require("./input-wrapper-J3mEKhvR.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-BOmr9YLv.cjs"),t=require("./class-map-Drv0_anQ.cjs"),n=require("./element-with-slot-D7sTqOr3.cjs");require("./icon-Dnv6LtPC.cjs");const r=require("./if-defined-2mkIDgOm.cjs"),i=require("./ref-Emu5PNxk.cjs"),a=require("./input-element-CSfDGslx.cjs"),o=require("./input-wrapper-CTMf4kCK.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}
@@ -6,7 +6,7 @@ import "./icon-JigbxxF7.js";
6
6
  import { t as l } from "./if-defined-Bebu3LXY.js";
7
7
  import { n as u, t as d } from "./ref-CCSGk4MP.js";
8
8
  import { t as f } from "./input-element-lLzfwdim.js";
9
- import { r as p } from "./input-wrapper-BoTugCvh.js";
9
+ import { r as p } from "./input-wrapper-C9K-_7g-.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);
@@ -1,4 +1,4 @@
1
- const e=require("./element-BOmr9YLv.cjs"),t=require("./class-map-Drv0_anQ.cjs"),n=require("./format-B8meU8Tm.cjs"),r=require("./element-with-slot-D7sTqOr3.cjs");require("./icon-Dnv6LtPC.cjs");const i=require("./if-defined-2mkIDgOm.cjs"),a=require("./ref-Emu5PNxk.cjs"),o=require("./input-element-CSfDGslx.cjs"),s=require("./input-wrapper-J3mEKhvR.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-BOmr9YLv.cjs"),t=require("./class-map-Drv0_anQ.cjs"),n=require("./format-B8meU8Tm.cjs"),r=require("./element-with-slot-D7sTqOr3.cjs");require("./icon-Dnv6LtPC.cjs");const i=require("./if-defined-2mkIDgOm.cjs"),a=require("./ref-Emu5PNxk.cjs"),o=require("./input-element-CSfDGslx.cjs"),s=require("./input-wrapper-CTMf4kCK.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"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oslokommune/punkt-elements",
3
- "version": "19.6.0",
3
+ "version": "19.8.0",
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": "52793889285e2b8365c81315dce280062c38a543"
87
+ "gitHead": "aac1152f60412d31e67493d4813afebe5dcea8bb"
88
88
  }
@@ -149,7 +149,7 @@ export class PktAlert extends PktElementWithSlot<IPktAlert> implements IPktAlert
149
149
  this.dispatchEvent(
150
150
  new CustomEvent('close', { detail: { origin: event }, bubbles: true, composed: true }),
151
151
  )
152
- // Historical support of old Vue implementations…
152
+ // Deprecated: beholdt for eldre Vue-oppsett. Bruk `close`, `on-close` fjernes i en senere hovedversjon.
153
153
  this.dispatchEvent(
154
154
  new CustomEvent('on-close', { detail: { origin: event }, bubbles: true, composed: true }),
155
155
  )
@@ -3,9 +3,13 @@ import { Ref, createRef } from 'lit/directives/ref.js'
3
3
  import { PktInputElement } from '@/base-elements/input-element'
4
4
  import { PktOptionsSlotController } from '@/controllers/pkt-options-controller'
5
5
  import { isMaxSelectionReached } from 'shared-utils/combobox/option-utils'
6
- import specs from 'componentSpecs/combobox.json'
6
+ import { COMBOBOX_DEFAULTS } from 'shared-types/combobox'
7
7
 
8
- import type { IPktComboboxOption, TPktComboboxTagPlacement } from './combobox-types'
8
+ import type {
9
+ IPktComboboxOption,
10
+ TPktComboboxDisplayValue,
11
+ TPktComboboxTagPlacement,
12
+ } from './combobox-types'
9
13
  import type { IPktStringsProps } from 'shared-strings'
10
14
  import PktListbox from '../listbox'
11
15
  import type { TComboboxMessageKey } from 'shared-utils/combobox'
@@ -24,15 +28,17 @@ export class ComboboxBase extends PktInputElement<IPktStringsProps<'combobox' |
24
28
  @property({ type: String, reflect: true }) value: string | string[] = ''
25
29
  @property({ type: Array }) options: IPktComboboxOption[] = []
26
30
  @property({ type: Array, attribute: 'default-options' }) defaultOptions: IPktComboboxOption[] = []
27
- @property({ type: Boolean, attribute: 'allow-user-input' }) allowUserInput: boolean = false
28
- @property({ type: Boolean }) typeahead: boolean = false
29
- @property({ type: Boolean, attribute: 'include-search' }) includeSearch: boolean = false
31
+ @property({ type: Boolean, attribute: 'allow-user-input' }) allowUserInput: boolean =
32
+ COMBOBOX_DEFAULTS.allowUserInput
33
+ @property({ type: Boolean }) typeahead: boolean = COMBOBOX_DEFAULTS.typeahead
34
+ @property({ type: Boolean, attribute: 'include-search' }) includeSearch: boolean =
35
+ COMBOBOX_DEFAULTS.includeSearch
30
36
  @property({ type: String, attribute: 'search-placeholder' }) searchPlaceholder: string | null =
31
37
  null
32
- @property({ type: Boolean }) multiple: boolean = false
38
+ @property({ type: Boolean }) multiple: boolean = COMBOBOX_DEFAULTS.multiple
33
39
  @property({ type: Number }) maxlength: number | null = null
34
- @property({ type: String, attribute: 'display-value-as' }) displayValueAs: string =
35
- specs.props.displayValueAs.default
40
+ @property({ type: String, attribute: 'display-value-as' })
41
+ displayValueAs: TPktComboboxDisplayValue = COMBOBOX_DEFAULTS.displayValueAs
36
42
  @property({ type: String, attribute: 'tag-placement' })
37
43
  tagPlacement: TPktComboboxTagPlacement | null = null
38
44
  // Internal use only — syncs to _isOptionsOpen in willUpdate(), but does not
@@ -1,4 +1,4 @@
1
- import type { IPktComboboxOption, TPktComboboxDisplayValue } from './combobox-types'
1
+ import type { IPktComboboxOption } from './combobox-types'
2
2
  import {
3
3
  findOptionByValue,
4
4
  getOptionDisplayText,
@@ -87,7 +87,7 @@ export class ComboboxValue extends ComboboxBase {
87
87
  ? getSingleValueForInput(valueFromOptions || '', this.options, this.displayValueAs)
88
88
  : getOptionDisplayText(
89
89
  findOptionByValue(this.options, valueFromOptions),
90
- this.displayValueAs as TPktComboboxDisplayValue,
90
+ this.displayValueAs,
91
91
  )
92
92
  }
93
93
 
@@ -1,6 +1,6 @@
1
1
  import '@testing-library/jest-dom'
2
2
 
3
- import spec from 'componentSpecs/combobox.json'
3
+ import spec from 'componentSpecs/combobox.spec'
4
4
  import './combobox'
5
5
  import { PktCombobox } from './combobox'
6
6
 
@@ -18,6 +18,7 @@ const cases: { attribute: string; property: keyof PktCombobox; set: string; expe
18
18
  { attribute: 'display-value-as', property: 'displayValueAs', set: 'value', expect: 'value' },
19
19
  { attribute: 'search-placeholder', property: 'searchPlaceholder', set: 'x', expect: 'x' },
20
20
  { attribute: 'tag-placement', property: 'tagPlacement', set: 'outside', expect: 'outside' },
21
+ { attribute: 'aria-describedby', property: 'ariaDescribedby', set: 'x', expect: 'x' },
21
22
  { attribute: 'defaultvalue', property: 'defaultValue', set: 'x', expect: 'x' },
22
23
  { attribute: 'errormessage', property: 'errorMessage', set: 'x', expect: 'x' },
23
24
  { attribute: 'helptextdropdown', property: 'helptextDropdown', set: 'x', expect: 'x' },
@@ -71,7 +72,7 @@ describe('PktCombobox attributes', () => {
71
72
  })
72
73
 
73
74
  test('every renamed attribute in the component spec is declared', () => {
74
- const renamed = Object.entries(spec.props)
75
+ const renamed = Object.entries(spec.props ?? {})
75
76
  .filter(([name, prop]) => 'attribute' in prop && prop.attribute !== name)
76
77
  .map(([, prop]) => (prop as { attribute: string }).attribute)
77
78
  // input-size and data-testid come from the shared input wrapper, not combobox
@@ -10,6 +10,7 @@ import type {
10
10
  TPktComboboxTagPlacement,
11
11
  TPktComboboxDisplayValue,
12
12
  } from './combobox-types'
13
+ import type { IPktComboboxBase } from 'shared-types/combobox'
13
14
  import { findOptionByValue, findOptionIndex } from 'shared-utils/combobox/option-utils'
14
15
  import { getSingleValueForInput } from 'shared-utils/combobox/input-utils'
15
16
  import { slotUtils, optionStateUtils } from './combobox-utils'
@@ -29,37 +30,36 @@ import '../listbox'
29
30
  // Re-export types for backward compatibility
30
31
  export type { IPktComboboxOption, TPktComboboxTagPlacement } from './combobox-types'
31
32
 
32
- export interface IPktCombobox extends IPktStringsProps<'combobox' | 'listbox'> {
33
- allowUserInput?: boolean
34
- typeahead?: boolean
35
- disabled?: boolean
36
- displayValueAs?: string
37
- errorMessage?: string
38
- fullwidth?: boolean
39
- hasError?: boolean
33
+ export interface IPktCombobox
34
+ extends
35
+ Omit<
36
+ IPktComboboxBase,
37
+ | 'form'
38
+ | 'ariaDescribedby'
39
+ | 'label'
40
+ | 'helptext'
41
+ | 'helptextDropdown'
42
+ | 'helptextDropdownButton'
43
+ | 'placeholder'
44
+ | 'searchPlaceholder'
45
+ | 'maxlength'
46
+ | 'tagPlacement'
47
+ | 'defaultValue'
48
+ | 'useWrapper'
49
+ >,
50
+ IPktStringsProps<'combobox' | 'listbox'> {
51
+ ariaDescribedby?: string | null
52
+ label?: string | null
40
53
  helptext?: string | null
41
54
  helptextDropdown?: string | null
55
+ /** @deprecated Bruk `strings={{ forms: { readMore: '…' } }}` eller `setPktStrings()`. */
42
56
  helptextDropdownButton?: string | null
43
- id?: string
44
- includeSearch?: boolean
45
- label?: string | null
46
- maxlength?: number | null
47
- minlength?: number | null
48
- multiple?: boolean
49
- name?: string
50
- optionalTag?: boolean
51
- optionalText?: string
52
- options?: IPktComboboxOption[]
53
- defaultOptions?: IPktComboboxOption[]
54
57
  placeholder?: string | null
55
- requiredTag?: boolean
56
- requiredText?: string
57
58
  searchPlaceholder?: string | null
59
+ maxlength?: number | null
60
+ minlength?: number | null
58
61
  tagPlacement?: TPktComboboxTagPlacement | null
59
- tagText?: string | null
60
- value?: string | string[]
61
62
  defaultValue?: string | string[] | null
62
- hasFieldset?: boolean | null
63
63
  useWrapper?: Booleanish
64
64
  isOpen?: boolean
65
65
  }
@@ -72,7 +72,7 @@ export interface IPktCombobox extends IPktStringsProps<'combobox' | 'listbox'> {
72
72
  export interface IPktComboboxAttributes {
73
73
  'allow-user-input'?: boolean
74
74
  'default-options'?: IPktComboboxOption[]
75
- 'display-value-as'?: string
75
+ 'display-value-as'?: TPktComboboxDisplayValue
76
76
  'include-search'?: boolean
77
77
  'search-placeholder'?: string | null
78
78
  'tag-placement'?: TPktComboboxTagPlacement | null
@@ -574,7 +574,7 @@ export class PktCombobox extends ComboboxHandlers implements IPktCombobox {
574
574
 
575
575
  private renderValueTag(option: IPktComboboxOption | null) {
576
576
  if (!option) return ''
577
- const displayAs = this.displayValueAs as TPktComboboxDisplayValue
577
+ const displayAs = this.displayValueAs
578
578
  switch (displayAs) {
579
579
  case 'prefixAndValue':
580
580
  return html`<span class="pkt-combobox__value">${option.prefix || ''} ${option.value}</span>`
@@ -52,6 +52,7 @@ export class PktInputWrapper extends PktElementWithSlot<Props> {
52
52
  @property({ type: String }) label: string = ''
53
53
  @property({ type: String }) helptext: string | null = null
54
54
  @property({ type: String }) helptextDropdown: string | null = null
55
+ /** @deprecated Bruk `strings={{ forms: { readMore: '…' } }}` eller `setPktStrings()`. */
55
56
  @property({ type: String }) helptextDropdownButton: string | null = null
56
57
  @property({ type: Boolean }) counter: boolean = specs.props.counter.default
57
58
  @property({ type: Number }) counterCurrent: number = 0
@@ -72,7 +72,7 @@ describe('PktMessagebox', () => {
72
72
  expect(messagebox.closable).toBe(false)
73
73
  expect(messagebox.compact).toBe(false)
74
74
  expect(messagebox.title).toBe('')
75
- expect(messagebox.skin).toBeUndefined()
75
+ expect(messagebox.skin).toBe('beige')
76
76
  })
77
77
 
78
78
  test('sets properties correctly', async () => {
@@ -3,20 +3,14 @@ import { slotContent } from '@/directives/slot-content'
3
3
  import { html, nothing, PropertyValues } from 'lit'
4
4
  import { classMap } from 'lit/directives/class-map.js'
5
5
  import { customElement, property, state } from 'lit/decorators.js'
6
- import specs from 'componentSpecs/messagebox.json'
7
6
 
8
7
  import '@/components/icon'
9
8
  import { updateClassAttribute } from '@/utils/classutils'
10
- import type { TMessageboxSkin } from 'shared-types'
9
+ import { MESSAGEBOX_DEFAULTS, type IPktMessageboxBase, type TMessageboxSkin } from 'shared-types'
11
10
 
12
11
  export type { TMessageboxSkin }
13
12
 
14
- export interface IPktMessagebox {
15
- skin?: TMessageboxSkin
16
- title?: string
17
- compact?: boolean
18
- closable?: boolean
19
- }
13
+ export interface IPktMessagebox extends IPktMessageboxBase {}
20
14
 
21
15
  export class PktMessagebox extends PktElementWithSlot implements IPktMessagebox {
22
16
  constructor() {
@@ -26,10 +20,10 @@ export class PktMessagebox extends PktElementWithSlot implements IPktMessagebox
26
20
 
27
21
  // Properties
28
22
 
29
- @property({ type: Boolean, reflect: true }) closable = specs.props.closable.default
30
- @property({ type: Boolean, reflect: true }) compact = specs.props.compact.default
23
+ @property({ type: Boolean, reflect: true }) closable: boolean = MESSAGEBOX_DEFAULTS.closable
24
+ @property({ type: Boolean, reflect: true }) compact: boolean = MESSAGEBOX_DEFAULTS.compact
31
25
  @property({ type: String, reflect: true }) title = ''
32
- @property({ type: String, reflect: true }) skin?: TMessageboxSkin = undefined
26
+ @property({ type: String, reflect: true }) skin?: TMessageboxSkin = MESSAGEBOX_DEFAULTS.skin
33
27
 
34
28
  @state() _isClosed: boolean = false
35
29
 
@@ -75,7 +69,7 @@ export class PktMessagebox extends PktElementWithSlot implements IPktMessagebox
75
69
  private close = (event: MouseEvent) => {
76
70
  this._isClosed = true
77
71
  this.dispatchEvent(new CustomEvent('close', { detail: { origin: event }, bubbles: true }))
78
- // Historical support of old Vue implementations…
72
+ // Deprecated: beholdt for eldre Vue-oppsett. Bruk `close`, `on-close` fjernes i en senere hovedversjon.
79
73
  this.dispatchEvent(new CustomEvent('on-close', { detail: { origin: event }, bubbles: true }))
80
74
  }
81
75
  }