@fremtind/jokul 0.27.3 → 0.27.5

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 (189) hide show
  1. package/README.md +9 -2
  2. package/build/build-stats.html +1 -1
  3. package/build/cjs/components/card/Card.cjs.map +1 -1
  4. package/build/cjs/components/card/CardImage.cjs.map +1 -1
  5. package/build/cjs/components/combobox/Combobox.cjs +1 -1
  6. package/build/cjs/components/combobox/Combobox.cjs.map +1 -1
  7. package/build/cjs/components/datepicker/DatePicker.cjs +1 -1
  8. package/build/cjs/components/datepicker/DatePicker.cjs.map +1 -1
  9. package/build/cjs/components/datepicker/internal/Calendar.cjs +1 -1
  10. package/build/cjs/components/datepicker/internal/Calendar.cjs.map +1 -1
  11. package/build/cjs/components/expander/Expander.cjs +1 -1
  12. package/build/cjs/components/expander/Expander.cjs.map +1 -1
  13. package/build/cjs/components/feedback/questions/ContactQuestion.cjs.map +1 -1
  14. package/build/cjs/components/flex/Flex.cjs.map +1 -1
  15. package/build/cjs/components/input-group/SupportLabel.cjs +1 -1
  16. package/build/cjs/components/input-group/SupportLabel.cjs.map +1 -1
  17. package/build/cjs/components/link-list/LinkList.cjs +1 -1
  18. package/build/cjs/components/link-list/LinkList.cjs.map +1 -1
  19. package/build/cjs/components/menu/MenuItem.cjs +1 -1
  20. package/build/cjs/components/menu/MenuItem.cjs.map +1 -1
  21. package/build/cjs/components/menu/MenuItemCheckbox.cjs +1 -1
  22. package/build/cjs/components/menu/MenuItemCheckbox.cjs.map +1 -1
  23. package/build/cjs/components/message/DismissButton.cjs +1 -1
  24. package/build/cjs/components/message/DismissButton.cjs.map +1 -1
  25. package/build/cjs/components/message/Message.cjs +1 -1
  26. package/build/cjs/components/message/Message.cjs.map +1 -1
  27. package/build/cjs/components/modal/Modal.cjs +1 -1
  28. package/build/cjs/components/modal/Modal.cjs.map +1 -1
  29. package/build/cjs/components/pagination/Pagination.cjs +1 -1
  30. package/build/cjs/components/pagination/Pagination.cjs.map +1 -1
  31. package/build/cjs/components/radio-panel/RadioPanel.cjs +1 -1
  32. package/build/cjs/components/radio-panel/RadioPanel.cjs.map +1 -1
  33. package/build/cjs/components/select/NativeSelect.cjs +1 -1
  34. package/build/cjs/components/select/NativeSelect.cjs.map +1 -1
  35. package/build/cjs/components/select/Select.cjs +1 -1
  36. package/build/cjs/components/select/Select.cjs.map +1 -1
  37. package/build/cjs/components/system-message/common/DismissButton.cjs +1 -1
  38. package/build/cjs/components/system-message/common/DismissButton.cjs.map +1 -1
  39. package/build/cjs/components/system-message/common/MessageIcon.cjs +1 -1
  40. package/build/cjs/components/system-message/common/MessageIcon.cjs.map +1 -1
  41. package/build/cjs/components/table/ExpandableTableRow.cjs +1 -1
  42. package/build/cjs/components/table/ExpandableTableRow.cjs.map +1 -1
  43. package/build/cjs/components/table/TableHeader.cjs +1 -1
  44. package/build/cjs/components/table/TableHeader.cjs.map +1 -1
  45. package/build/cjs/components/table/TablePagination.cjs +1 -1
  46. package/build/cjs/components/table/TablePagination.cjs.map +1 -1
  47. package/build/cjs/components/tag/Tag.cjs +1 -1
  48. package/build/cjs/components/tag/Tag.cjs.map +1 -1
  49. package/build/cjs/components/text-input/BaseTextInput.cjs.map +1 -1
  50. package/build/cjs/components/text-input/BaseTextInput.d.cts +2 -2
  51. package/build/cjs/components/toast/Toast.cjs +1 -1
  52. package/build/cjs/components/toast/Toast.cjs.map +1 -1
  53. package/build/cjs/components/toggle-switch/ToggleSwitch.cjs +1 -1
  54. package/build/cjs/components/toggle-switch/ToggleSwitch.cjs.map +1 -1
  55. package/build/cjs/components/toggle-switch/ToggleSwitch.d.cts +1 -1
  56. package/build/cjs/components/tooltip/PopupTip.cjs +1 -1
  57. package/build/cjs/components/tooltip/PopupTip.cjs.map +1 -1
  58. package/build/cjs/components/tooltip/PopupTip.d.cts +1 -1
  59. package/build/es/components/card/Card.js.map +1 -1
  60. package/build/es/components/card/CardImage.js.map +1 -1
  61. package/build/es/components/combobox/Combobox.js +1 -1
  62. package/build/es/components/combobox/Combobox.js.map +1 -1
  63. package/build/es/components/datepicker/DatePicker.js +1 -1
  64. package/build/es/components/datepicker/DatePicker.js.map +1 -1
  65. package/build/es/components/datepicker/internal/Calendar.js +1 -1
  66. package/build/es/components/datepicker/internal/Calendar.js.map +1 -1
  67. package/build/es/components/expander/Expander.js +1 -1
  68. package/build/es/components/expander/Expander.js.map +1 -1
  69. package/build/es/components/feedback/questions/ContactQuestion.js.map +1 -1
  70. package/build/es/components/flex/Flex.js.map +1 -1
  71. package/build/es/components/input-group/SupportLabel.js +1 -1
  72. package/build/es/components/input-group/SupportLabel.js.map +1 -1
  73. package/build/es/components/link-list/LinkList.js +1 -1
  74. package/build/es/components/link-list/LinkList.js.map +1 -1
  75. package/build/es/components/menu/MenuItem.js +1 -1
  76. package/build/es/components/menu/MenuItem.js.map +1 -1
  77. package/build/es/components/menu/MenuItemCheckbox.js +1 -1
  78. package/build/es/components/menu/MenuItemCheckbox.js.map +1 -1
  79. package/build/es/components/message/DismissButton.js +1 -1
  80. package/build/es/components/message/DismissButton.js.map +1 -1
  81. package/build/es/components/message/Message.js +1 -1
  82. package/build/es/components/message/Message.js.map +1 -1
  83. package/build/es/components/modal/Modal.js +1 -1
  84. package/build/es/components/modal/Modal.js.map +1 -1
  85. package/build/es/components/pagination/Pagination.js +1 -1
  86. package/build/es/components/pagination/Pagination.js.map +1 -1
  87. package/build/es/components/radio-panel/RadioPanel.js +1 -1
  88. package/build/es/components/radio-panel/RadioPanel.js.map +1 -1
  89. package/build/es/components/select/NativeSelect.js +1 -1
  90. package/build/es/components/select/NativeSelect.js.map +1 -1
  91. package/build/es/components/select/Select.js +1 -1
  92. package/build/es/components/select/Select.js.map +1 -1
  93. package/build/es/components/system-message/common/DismissButton.js +1 -1
  94. package/build/es/components/system-message/common/DismissButton.js.map +1 -1
  95. package/build/es/components/system-message/common/MessageIcon.js +1 -1
  96. package/build/es/components/system-message/common/MessageIcon.js.map +1 -1
  97. package/build/es/components/table/ExpandableTableRow.js +1 -1
  98. package/build/es/components/table/ExpandableTableRow.js.map +1 -1
  99. package/build/es/components/table/TableHeader.js +1 -1
  100. package/build/es/components/table/TableHeader.js.map +1 -1
  101. package/build/es/components/table/TablePagination.js +1 -1
  102. package/build/es/components/table/TablePagination.js.map +1 -1
  103. package/build/es/components/tag/Tag.js +1 -1
  104. package/build/es/components/tag/Tag.js.map +1 -1
  105. package/build/es/components/text-input/BaseTextInput.d.ts +2 -2
  106. package/build/es/components/text-input/BaseTextInput.js.map +1 -1
  107. package/build/es/components/toast/Toast.js +1 -1
  108. package/build/es/components/toast/Toast.js.map +1 -1
  109. package/build/es/components/toggle-switch/ToggleSwitch.d.ts +1 -1
  110. package/build/es/components/toggle-switch/ToggleSwitch.js +1 -1
  111. package/build/es/components/toggle-switch/ToggleSwitch.js.map +1 -1
  112. package/build/es/components/tooltip/PopupTip.d.ts +1 -1
  113. package/build/es/components/tooltip/PopupTip.js +1 -1
  114. package/build/es/components/tooltip/PopupTip.js.map +1 -1
  115. package/package.json +2 -2
  116. package/styles/components/accordion/accordion.css +13 -5
  117. package/styles/components/accordion/accordion.min.css +7 -1
  118. package/styles/components/accordion/accordion.scss +17 -6
  119. package/styles/components/button/button.css +2 -2
  120. package/styles/components/button/button.min.css +1 -1
  121. package/styles/components/button/button.scss +2 -1
  122. package/styles/components/card/card.css +3 -1
  123. package/styles/components/card/card.scss +3 -1
  124. package/styles/components/checkbox/checkbox.css +4 -4
  125. package/styles/components/checkbox/checkbox.min.css +1 -1
  126. package/styles/components/checkbox/checkbox.scss +15 -5
  127. package/styles/components/combobox/combobox.css +4 -2
  128. package/styles/components/combobox/combobox.scss +20 -7
  129. package/styles/components/datepicker/_calendar.scss +6 -3
  130. package/styles/components/datepicker/datepicker.css +6 -3
  131. package/styles/components/datepicker/datepicker.scss +2 -1
  132. package/styles/components/feedback/feedback.css +2 -2
  133. package/styles/components/feedback/feedback.min.css +1 -1
  134. package/styles/components/feedback/feedback.scss +4 -1
  135. package/styles/components/icon/icon.scss +2 -2
  136. package/styles/components/input-group/_labels.scss +13 -5
  137. package/styles/components/input-group/input-group.css +2 -2
  138. package/styles/components/input-group/input-group.min.css +1 -1
  139. package/styles/components/input-group/input-group.scss +4 -1
  140. package/styles/components/link/link.scss +14 -2
  141. package/styles/components/list/list.scss +21 -6
  142. package/styles/components/loader/loader.css +6 -6
  143. package/styles/components/loader/loader.min.css +1 -1
  144. package/styles/components/loader/skeleton-loader.css +5 -5
  145. package/styles/components/loader/skeleton-loader.min.css +1 -1
  146. package/styles/components/loader/skeleton-loader.scss +2 -1
  147. package/styles/components/logo/logo.scss +12 -4
  148. package/styles/components/menu/menu.scss +2 -1
  149. package/styles/components/message/message.css +6 -3
  150. package/styles/components/message/message.min.css +1 -1
  151. package/styles/components/message/message.scss +11 -4
  152. package/styles/components/progress-bar/progress-bar.css +2 -2
  153. package/styles/components/progress-bar/progress-bar.min.css +1 -1
  154. package/styles/components/radio-button/radio-button.css +2 -2
  155. package/styles/components/radio-button/radio-button.min.css +1 -1
  156. package/styles/components/radio-button/radio-button.scss +24 -9
  157. package/styles/components/radio-panel/radio-panel.css +2 -2
  158. package/styles/components/radio-panel/radio-panel.min.css +1 -1
  159. package/styles/components/radio-panel/radio-panel.scss +2 -1
  160. package/styles/components/select/select.css +6 -3
  161. package/styles/components/select/select.scss +20 -7
  162. package/styles/components/system-message/system-message.css +2 -2
  163. package/styles/components/system-message/system-message.min.css +1 -1
  164. package/styles/components/system-message/system-message.scss +8 -3
  165. package/styles/components/table/_table-cell.scss +10 -4
  166. package/styles/components/table/_table-head.scss +2 -1
  167. package/styles/components/table/_table-row.scss +21 -9
  168. package/styles/components/tabs/tabs.css +6 -3
  169. package/styles/components/tabs/tabs.scss +6 -3
  170. package/styles/components/text-input/text-input.css +4 -2
  171. package/styles/components/text-input/text-input.scss +19 -8
  172. package/styles/components/toast/toast.css +7 -5
  173. package/styles/components/toast/toast.min.css +1 -1
  174. package/styles/components/toast/toast.scss +11 -4
  175. package/styles/components/toggle-switch/_toggle-slider.scss +2 -1
  176. package/styles/components/toggle-switch/toggle-switch.css +2 -1
  177. package/styles/components/toggle-switch/toggle-switch.scss +2 -1
  178. package/styles/components/tooltip/tooltip.scss +7 -2
  179. package/styles/core/_spacing.scss +12 -3
  180. package/styles/core/core.scss +7 -2
  181. package/styles/core/jkl/_convert.scss +4 -1
  182. package/styles/core/jkl/_helpers.scss +7 -1
  183. package/styles/core/jkl/_ornaments.scss +3 -1
  184. package/styles/core/jkl/_spacing.scss +4 -1
  185. package/styles/core/jkl/_tokens.scss +12 -4
  186. package/styles/core/jkl/_typography.scss +14 -6
  187. package/styles/fonts/webfonts.scss +14 -7
  188. package/styles/styles.css +86 -57
  189. package/styles/styles.min.css +7 -1
@@ -1,2 +1,2 @@
1
- import{jsx as o,jsxs as e}from"react/jsx-runtime";import{c as n}from"../../../clsx-BeLtu-UY.js";import{useState as t,useRef as i,useEffect as r,useCallback as a,useMemo as s}from"react";import{useAnimatedHeight as c}from"../../hooks/useAnimatedHeight/useAnimatedHeight.js";import{useId as l}from"../../hooks/useId/useId.js";import{useListNavigation as u}from"../../hooks/useListNavigation/useListNavigation.js";import{ArrowVerticalAnimated as p}from"../icon/icons/animated/ArrowVerticalAnimated.js";import"../icon/Icon.js";import"../icon/icons/animated/ArrowHorizontalAnimated.js";import"../icon/icons/animated/PlusRemoveAnimated.js";import"../icon/icons/ArrowDownIcon.js";import"../icon/icons/ArrowLeftIcon.js";import"../icon/icons/ArrowNorthEastIcon.js";import"../icon/icons/ArrowRightIcon.js";import"../icon/icons/ArrowUpIcon.js";import"../icon/icons/CalendarIcon.js";import{CheckIcon as m}from"../icon/icons/CheckIcon.js";import"../icon/icons/ChevronDownIcon.js";import"../icon/icons/ChevronLeftIcon.js";import"../icon/icons/ChevronRightIcon.js";import"../icon/icons/ChevronUpIcon.js";import"../icon/icons/CloseIcon.js";import"../icon/icons/CopyIcon.js";import"../icon/icons/DotsIcon.js";import"../icon/icons/DragIcon.js";import"../icon/icons/ErrorIcon.js";import"../icon/icons/GreenCheckIcon.js";import"../icon/icons/HamburgerIcon.js";import"../icon/icons/InfoIcon.js";import"../icon/icons/LinkIcon.js";import"../icon/icons/PlusIcon.js";import"../icon/icons/QuestionIcon.js";import"../icon/icons/RedCrossIcon.js";import"../icon/icons/SearchIcon.js";import"../icon/icons/SuccessIcon.js";import"../icon/icons/WarningIcon.js";import"../icon/icons/MinusIcon.js";import"../icon/icons/ThumbDownIcon.js";import"../icon/icons/ThumbUpIcon.js";import"../icon/icons/TrashCanIcon.js";import"../icon/icons/PenIcon.js";import{IconButton as d}from"../icon-button/IconButton.js";import{InputGroup as b}from"../input-group/InputGroup.js";import{Tag as j}from"../tag/Tag.js";import{Tooltip as v}from"../tooltip/Tooltip.js";import{TooltipContent as f}from"../tooltip/TooltipContent.js";import{TooltipTrigger as g}from"../tooltip/TooltipTrigger.js";function h(o){return"string"==typeof o?{value:o,label:o}:o}const k=({id:k,placeholder:_,items:I,onChange:x,onFocus:w,onBlur:y,value:C,label:A,noMatchingOption:L,labelProps:T,helpLabel:N,errorLabel:$,width:D,density:P,name:B,className:E,invalid:F,hasTagHover:M})=>{var O,S;const H=l(k||"jkl-combobox",{generateSuffix:!k}),K=`${H}_label`,R=`${H}_button`,V=`${H}_search-input`,[U,G]=t(C||[]),[q,z]=t(!0),[Q,W]=t(!1),[J,X]=t(""),[Y,Z]=t(!1),[oo,eo]=t(!1),no=i(null),to=i(null),io=i(!1);r((()=>{X(""),Q&&no.current&&no.current.focus()}),[Q]),r((()=>{G((o=>C||o))}),[C]);const ro=o=>!!U&&U.some((e=>e.value===o.value)),ao=a((o=>U.filter((e=>e.value!==o))),[U]),so=a(((o,e)=>{let n=ao(e);G(n),x({type:"change",target:{name:B,value:e,selectedOptions:n}}),o.stopPropagation(),0===n.length&&eo(!1)}),[ao,G,x,B,eo]),co=a((o=>{var e;let n;if(U.some((e=>e.value===o)))n=ao(o);else{const e=I.find((e=>e.value===o));n=[...U,e]}null==(e=no.current)||e.focus(),G(n),x({type:"change",target:{name:B,value:o,selectedOptions:n}})}),[U,G,x,B,ao,I]),lo=o=>{var e;null==(e=no.current)||e.focus(),W(!0),X(o.target.value)},uo=s((()=>{if(!J)return I;const o=I.filter((o=>o.label.toLowerCase().indexOf(J.toLowerCase())>=0));return Z(0===o.length),o}),[J,I]),[po,mo]=t(null!=(O=uo[0])&&O.value?`${H}-${null==(S=uo[0])?void 0:S.value}`:void 0);r((()=>{z(!Q)}),[Q]),r((()=>{const o=o=>{"Escape"===o.key&&Q&&W(!1)};return typeof window<"u"&&window.addEventListener("keydown",o),()=>{typeof window<"u"&&Q&&window.removeEventListener("keydown",o)}}),[W,Q]);const bo=a((o=>{o?no.current&&no.current.focus():io.current&&to.current&&to.current.focus()}),[]),jo=a((()=>{io.current||(w&&w({type:"change",target:{name:B,value:(null==U?void 0:U[0].value)||"",selectedOptions:U}}),io.current=!0,W(!0))}),[w,U,B]),[vo]=c(Q,{onFirstVisible:bo,onTransitionEnd:bo});u({ref:vo});const fo=i(null),go=a((o=>{var e,n;const t=fo.current;t&&t.contains(o.relatedTarget)||(X(""),y&&(y({type:"blur",target:{name:B,value:(null==(e=null==U?void 0:U[0])?void 0:e.value)||"",selectedOptions:U}}),null==(n=to.current)||n.dispatchEvent(new Event("focusout",{bubbles:!0}))),io.current=!1,W(!1))}),[y,B,U]),ho=a((o=>{o.target.focus({preventScroll:!0})}),[]),ko=a((o=>{var e;if("ArrowDown"===o.key){o.preventDefault(),o.stopPropagation();const n=vo.current;n&&(null==(e=n.querySelector('[role="option"]'))||e.focus())}else"Escape"===o.key&&(o.preventDefault(),o.stopPropagation(),W(!1));if(o.metaKey&&"a"===o.key||o.ctrlKey&&"a"===o.key){o.preventDefault(),o.stopPropagation();const e=U.map((o=>({...o,isMarked:!0})));eo(!0),G(e)}else if("Backspace"===o.key)if(o.stopPropagation(),eo(!1),U.some((o=>o.isMarked))){const o=U.filter((o=>!o.isMarked));G(o),X("")}else U.length>0&&""===J&&so(o,U[U.length-1].value)}),[U,J,vo,so]),_o=a((o=>{if("Tab"===o.key)no.current&&(o.preventDefault(),o.stopPropagation(),o.shiftKey||W(!1),no.current.focus());else if("ArrowUp"===o.key&&vo.current&&no.current){const e=vo.current.querySelector('[role="option"]:not([hidden])');o.currentTarget.id===(null==e?void 0:e.id)&&no.current&&no.current.focus()}}),[W,vo]),Io=U.length>=1;return o(b,{label:A,id:V,ref:fo,"data-testid":"jkl-combobox",className:n("jkl-combobox",E,{"jkl-combobox--invalid":!!$||F,"jkl-combobox--menu-open":Q,"jkl-combobox--menu-closed":!Q&&Io}),labelProps:{id:K,...T},helpLabel:N,errorLabel:$,density:P,render:t=>e("div",{className:n("jkl-combobox__wrapper",{"jkl-combobox__wrapper--active-value":Io}),style:{width:D},tabIndex:-1,onFocus:jo,onBlur:go,children:[e("div",{className:"jkl-combobox__tags","data-testid":"jkl-combobox__tags",children:[U.map(h).map((n=>o(j,{className:`jkl-tag ${oo&&"jkl-tag__marked"}`,"data-testid":"jkl-tag",dismissAction:{onClick:o=>{no.current&&no.current.focus(),so(o,n.value)},onBlur:go,label:`Fjern ${n.value}`},children:M?e(v,{children:[e(g,{children:[" ",o("span",{"aria-hidden":"true","data-testid":"jkl-tag__content",children:n.tagLabel?n.tagLabel:n.label})]}),o(f,{children:n.label})]},n.value):o("span",{"aria-hidden":"true","data-testid":"jkl-tag__content",children:n.tagLabel?n.tagLabel:n.label})},n.value))),o("input",{...t,className:"jkl-combobox__search-input",onChange:lo,"data-testid":"jkl-combobox__search-input",onFocus:jo,onBlur:go,onKeyDown:ko,value:J,ref:no,"aria-controls":H,role:"combobox","aria-autocomplete":"list","aria-expanded":Q,placeholder:U.length>0?"":_,autoComplete:"off"})]}),e("div",{className:"jkl-combobox__menu",role:"listbox",ref:vo,id:H,"aria-labelledby":K,"aria-multiselectable":"true","aria-activedescendant":po,onFocus:jo,onBlur:go,tabIndex:-1,children:[uo.map(((n,t)=>e("button",{type:"button",id:`${H}__${n.value}`,"aria-selected":ro(n),role:"option",value:n.value,onBlur:go,className:`jkl-combobox__option ${ro(n)&&"jkl-combobox__option--selected"}`,"data-testid":"jkl-combobox__option","data-testautoid":`jkl-combobox__option-${t}`,onFocus:jo,onKeyDown:_o,onClick:o=>{mo(`${H}__${n.value}`),o.stopPropagation(),co(n.value),X("")},onMouseOver:ho,children:[n.description?e("span",{children:[n.label,o("span",{className:"jkl-combobox__option-description",children:n.description})]}):n.label,ro(n)?e("span",{children:[o(m,{})," "]}):null]},`${H}-${n.value}`))),Y&&o("div",{className:"jkl-combobox__no-option",children:L})]}),o("div",{className:"jkl-combobox__actions",children:o(d,{id:R,onFocus:jo,onBlur:go,className:"jkl-combobox__button","data-testid":"jkl-combobox__button","aria-label":`${U.map((o=>o.label))||"Velg"},${A}`,"aria-expanded":Q,"aria-controls":H,role:"button",onClick:()=>W(!0),onMouseDown:o=>{var e;o.preventDefault(),null==(e=to.current)||e.focus()},children:o(p,{pointingDown:q})})})]})})};k.displayName="Combobox";export{k as Combobox,h as getComboboxValuePair};
1
+ import{jsx as e,jsxs as o}from"react/jsx-runtime";import{c as t}from"../../../clsx-BeLtu-UY.js";import{useState as a,useRef as n,useEffect as l,useCallback as r,useMemo as i}from"react";import{useAnimatedHeight as s}from"../../hooks/useAnimatedHeight/useAnimatedHeight.js";import{useId as c}from"../../hooks/useId/useId.js";import{useListNavigation as u}from"../../hooks/useListNavigation/useListNavigation.js";import{ArrowVerticalAnimated as d}from"../icon/icons/animated/ArrowVerticalAnimated.js";import{CheckIcon as p}from"../icon/icons/CheckIcon.js";import{IconButton as m}from"../icon-button/IconButton.js";import{InputGroup as b}from"../input-group/InputGroup.js";import{Tag as v}from"../tag/Tag.js";import{Tooltip as f}from"../tooltip/Tooltip.js";import{TooltipContent as g}from"../tooltip/TooltipContent.js";import{TooltipTrigger as h}from"../tooltip/TooltipTrigger.js";function k(e){return"string"==typeof e?{value:e,label:e}:e}const _=({id:_,placeholder:j,items:x,onChange:y,onFocus:w,onBlur:$,value:C,label:N,noMatchingOption:L,labelProps:T,helpLabel:I,errorLabel:A,width:B,density:D,name:P,className:E,invalid:F,hasTagHover:M})=>{var O,K;const S=c(_||"jkl-combobox",{generateSuffix:!_}),V=`${S}_label`,H=`${S}_button`,q=`${S}_search-input`,[G,R]=a(C||[]),[U,z]=a(!0),[J,Q]=a(!1),[W,X]=a(""),[Y,Z]=a(!1),[ee,oe]=a(!1),te=n(null),ae=n(null),ne=n(!1);l((()=>{X(""),J&&te.current&&te.current.focus()}),[J]),l((()=>{R((e=>C||e))}),[C]);const le=e=>!!G&&G.some((o=>o.value===e.value)),re=r((e=>G.filter((o=>o.value!==e))),[G]),ie=r(((e,o)=>{let t=re(o);R(t),y({type:"change",target:{name:P,value:o,selectedOptions:t}}),e.stopPropagation(),0===t.length&&oe(!1)}),[re,R,y,P,oe]),se=r((e=>{var o;let t;if(G.some((o=>o.value===e)))t=re(e);else{const o=x.find((o=>o.value===e));t=[...G,o]}null==(o=te.current)||o.focus(),R(t),y({type:"change",target:{name:P,value:e,selectedOptions:t}})}),[G,R,y,P,re,x]),ce=e=>{var o;null==(o=te.current)||o.focus(),Q(!0),X(e.target.value)},ue=i((()=>{if(!W)return x;const e=x.filter((e=>e.label.toLowerCase().indexOf(W.toLowerCase())>=0));return Z(0===e.length),e}),[W,x]),[de,pe]=a(null!=(O=ue[0])&&O.value?`${S}-${null==(K=ue[0])?void 0:K.value}`:void 0);l((()=>{z(!J)}),[J]),l((()=>{const e=e=>{"Escape"===e.key&&J&&Q(!1)};return typeof window<"u"&&window.addEventListener("keydown",e),()=>{typeof window<"u"&&J&&window.removeEventListener("keydown",e)}}),[Q,J]);const me=r((e=>{e?te.current&&te.current.focus():ne.current&&ae.current&&ae.current.focus()}),[]),be=r((()=>{ne.current||(w&&w({type:"change",target:{name:P,value:(null==G?void 0:G[0].value)||"",selectedOptions:G}}),ne.current=!0,Q(!0))}),[w,G,P]),[ve]=s(J,{onFirstVisible:me,onTransitionEnd:me});u({ref:ve});const fe=n(null),ge=r((e=>{var o,t;const a=fe.current;a&&a.contains(e.relatedTarget)||(X(""),$&&($({type:"blur",target:{name:P,value:(null==(o=null==G?void 0:G[0])?void 0:o.value)||"",selectedOptions:G}}),null==(t=ae.current)||t.dispatchEvent(new Event("focusout",{bubbles:!0}))),ne.current=!1,Q(!1))}),[$,P,G]),he=r((e=>{e.target.focus({preventScroll:!0})}),[]),ke=r((e=>{var o;if("ArrowDown"===e.key){e.preventDefault(),e.stopPropagation();const t=ve.current;t&&(null==(o=t.querySelector('[role="option"]'))||o.focus())}else"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),Q(!1));if(e.metaKey&&"a"===e.key||e.ctrlKey&&"a"===e.key){e.preventDefault(),e.stopPropagation();const o=G.map((e=>({...e,isMarked:!0})));oe(!0),R(o)}else if("Backspace"===e.key)if(e.stopPropagation(),oe(!1),G.some((e=>e.isMarked))){const e=G.filter((e=>!e.isMarked));R(e),X("")}else G.length>0&&""===W&&ie(e,G[G.length-1].value)}),[G,W,ve,ie]),_e=r((e=>{if("Tab"===e.key)te.current&&(e.preventDefault(),e.stopPropagation(),e.shiftKey||Q(!1),te.current.focus());else if("ArrowUp"===e.key&&ve.current&&te.current){const o=ve.current.querySelector('[role="option"]:not([hidden])');e.currentTarget.id===(null==o?void 0:o.id)&&te.current&&te.current.focus()}}),[Q,ve]),je=G.length>=1;return e(b,{label:N,id:q,ref:fe,"data-testid":"jkl-combobox",className:t("jkl-combobox",E,{"jkl-combobox--invalid":!!A||F,"jkl-combobox--menu-open":J,"jkl-combobox--menu-closed":!J&&je}),labelProps:{id:V,...T},helpLabel:I,errorLabel:A,density:D,render:a=>o("div",{className:t("jkl-combobox__wrapper",{"jkl-combobox__wrapper--active-value":je}),style:{width:B},tabIndex:-1,onFocus:be,onBlur:ge,children:[o("div",{className:"jkl-combobox__tags","data-testid":"jkl-combobox__tags",children:[G.map(k).map((t=>e(v,{className:`jkl-tag ${ee&&"jkl-tag__marked"}`,"data-testid":"jkl-tag",dismissAction:{onClick:e=>{te.current&&te.current.focus(),ie(e,t.value)},onBlur:ge,label:`Fjern ${t.value}`},children:M?o(f,{children:[o(h,{children:[" ",e("span",{"aria-hidden":"true","data-testid":"jkl-tag__content",children:t.tagLabel?t.tagLabel:t.label})]}),e(g,{children:t.label})]},t.value):e("span",{"aria-hidden":"true","data-testid":"jkl-tag__content",children:t.tagLabel?t.tagLabel:t.label})},t.value))),e("input",{...a,className:"jkl-combobox__search-input",onChange:ce,"data-testid":"jkl-combobox__search-input",onFocus:be,onBlur:ge,onKeyDown:ke,value:W,ref:te,"aria-controls":S,role:"combobox","aria-autocomplete":"list","aria-expanded":J,placeholder:G.length>0?"":j,autoComplete:"off"})]}),o("div",{className:"jkl-combobox__menu",role:"listbox",ref:ve,id:S,"aria-labelledby":V,"aria-multiselectable":"true","aria-activedescendant":de,onFocus:be,onBlur:ge,tabIndex:-1,children:[ue.map(((t,a)=>o("button",{type:"button",id:`${S}__${t.value}`,"aria-selected":le(t),role:"option",value:t.value,onBlur:ge,className:`jkl-combobox__option ${le(t)&&"jkl-combobox__option--selected"}`,"data-testid":"jkl-combobox__option","data-testautoid":`jkl-combobox__option-${a}`,onFocus:be,onKeyDown:_e,onClick:e=>{pe(`${S}__${t.value}`),e.stopPropagation(),se(t.value),X("")},onMouseOver:he,children:[t.description?o("span",{children:[t.label,e("span",{className:"jkl-combobox__option-description",children:t.description})]}):t.label,le(t)?o("span",{children:[e(p,{})," "]}):null]},`${S}-${t.value}`))),Y&&e("div",{className:"jkl-combobox__no-option",children:L})]}),e("div",{className:"jkl-combobox__actions",children:e(m,{id:H,onFocus:be,onBlur:ge,className:"jkl-combobox__button","data-testid":"jkl-combobox__button","aria-label":`${G.map((e=>e.label))||"Velg"},${N}`,"aria-expanded":J,"aria-controls":S,role:"button",onClick:()=>Q(!0),onMouseDown:e=>{var o;e.preventDefault(),null==(o=ae.current)||o.focus()},children:e(d,{pointingDown:U})})})]})})};_.displayName="Combobox";export{_ as Combobox,k as getComboboxValuePair};
2
2
  //# sourceMappingURL=Combobox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Combobox.js","sources":["../../../../src/components/combobox/Combobox.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, {\n ChangeEvent,\n FC,\n FocusEvent,\n KeyboardEvent,\n MouseEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { Density } from \"../../core/types.js\";\nimport { useAnimatedHeight } from \"../../hooks/useAnimatedHeight/useAnimatedHeight.js\";\nimport { useId } from \"../../hooks/useId/useId.js\";\nimport { useListNavigation } from \"../../hooks/useListNavigation/useListNavigation.js\";\nimport { ValuePair } from \"../../utilities/valuePair.js\";\nimport { ArrowVerticalAnimated } from \"../icon/icons/animated/ArrowVerticalAnimated.js\";\nimport { CheckIcon } from \"../icon/index.js\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { InputGroup, InputGroupProps } from \"../input-group/InputGroup.js\";\nimport { LabelProps } from \"../input-group/Label.js\";\nimport { Tag } from \"../tag/Tag.js\";\nimport { Tooltip } from \"../tooltip/Tooltip.js\";\nimport { TooltipContent } from \"../tooltip/TooltipContent.js\";\nimport { TooltipTrigger } from \"../tooltip/TooltipTrigger.js\";\n\nexport type ComboboxValuePair = ValuePair & {\n tagLabel?: string;\n isMarked?: boolean;\n};\n\nexport function getComboboxValuePair(\n item: string | ComboboxValuePair,\n): ComboboxValuePair {\n return typeof item === \"string\" ? { value: item, label: item } : item;\n}\n\ninterface PartialChangeEvent\n extends Partial<Omit<ChangeEvent<HTMLElement>, \"target\">> {\n type: \"change\" | \"blur\";\n target: {\n name: string;\n value: string;\n selectedOptions: Array<ValuePair>;\n };\n}\n\ntype ChangeEventHandler = (event: PartialChangeEvent) => void;\n\ninterface ComboboxProps extends InputGroupProps {\n id?: string;\n placeholder?: string;\n labelProps?: Omit<\n LabelProps,\n \"children\" | \"density\" | \"htmlFor\" | \"standAlone\"\n >;\n items: Array<ValuePair>;\n noMatchingOption?: string;\n label: string;\n name: string;\n value?: Array<ValuePair>;\n density?: Density;\n width?: string;\n helpLabel?: string;\n errorLabel?: string;\n className?: string;\n invalid?: boolean;\n hasTagHover?: boolean;\n onChange: ChangeEventHandler;\n onBlur?: ChangeEventHandler;\n onFocus?: ChangeEventHandler;\n}\n\nexport const Combobox: FC<ComboboxProps> = ({\n id,\n placeholder,\n items,\n onChange,\n onFocus,\n onBlur,\n value,\n label,\n noMatchingOption,\n labelProps,\n helpLabel,\n errorLabel,\n width,\n density,\n name,\n className,\n invalid,\n hasTagHover,\n}) => {\n const listId = useId(id || \"jkl-combobox\", { generateSuffix: !id });\n const labelId = `${listId}_label`;\n const buttonId = `${listId}_button`;\n const inputId = `${listId}_search-input`;\n\n const [selectedValue, setSelectedValue] = useState<\n Array<ComboboxValuePair>\n >(value || []);\n const [isPointingDown, setIsPointingDown] = useState<boolean>(true);\n const [showMenu, setShowMenu] = useState<boolean>(false);\n const [searchValue, setSearchValue] = useState<string>(\"\");\n const [noResults, setNoResults] = useState(false);\n const [marked, setMarked] = useState<boolean>(false);\n\n const searchRef = useRef<HTMLInputElement>(null);\n const inputRef = useRef<HTMLDivElement>(null);\n const focusInsideRef = useRef(false);\n\n useEffect(() => {\n setSearchValue(\"\");\n if (showMenu && searchRef.current) {\n searchRef.current.focus();\n }\n }, [showMenu]);\n\n useEffect(() => {\n setSelectedValue((prev) => value || prev);\n }, [value]);\n\n // Funksjon for å stile valgt element\n const isSelected = (option: ValuePair) => {\n if (!selectedValue) {\n return false;\n } else {\n return selectedValue.some((value) => value.value === option.value);\n }\n };\n\n // Fjerne ett eller flere valg\n const removeOption = useCallback(\n (option: string) => {\n return selectedValue.filter((value) => value.value !== option);\n },\n [selectedValue],\n );\n\n const onTagRemove = useCallback(\n (\n e:\n | React.MouseEvent<HTMLButtonElement, globalThis.MouseEvent>\n | React.KeyboardEvent<HTMLInputElement>,\n option: string,\n ) => {\n let newValue = removeOption(option);\n setSelectedValue(newValue);\n onChange({\n type: \"change\",\n target: { name, value: option, selectedOptions: newValue },\n });\n e.stopPropagation();\n\n if (newValue.length === 0) {\n setMarked(false);\n }\n },\n [removeOption, setSelectedValue, onChange, name, setMarked],\n );\n\n // Håndtere valgt verdi i listen\n const onItemClick = useCallback(\n (option: string) => {\n let newValue: Array<ValuePair>;\n\n if (selectedValue.some((value) => value.value === option)) {\n newValue = removeOption(option);\n } else {\n const item = items.find((i) => i.value === option);\n newValue = [...selectedValue, item as ValuePair];\n }\n searchRef.current?.focus();\n setSelectedValue(newValue);\n onChange({\n type: \"change\",\n target: { name, value: option, selectedOptions: newValue },\n });\n },\n [selectedValue, setSelectedValue, onChange, name, removeOption, items],\n );\n\n // Funksjon for søk\n const onSearch = (e: {\n target: { value: React.SetStateAction<string> };\n }) => {\n searchRef.current?.focus();\n setShowMenu(true);\n setSearchValue(e.target.value);\n };\n\n const options = useMemo(() => {\n if (!searchValue) {\n return items;\n }\n\n const filteredOptions = items.filter(\n (option) =>\n option.label.toLowerCase().indexOf(searchValue.toLowerCase()) >=\n 0,\n );\n\n setNoResults(filteredOptions.length === 0);\n\n return filteredOptions;\n }, [searchValue, items]);\n\n // Det første elementet i listen skal være aktivt fram til brukeren klikker på noe annet\n const [activeDescendant, setActiveDescendant] = useState<\n string | undefined\n >(options[0]?.value ? `${listId}-${options[0]?.value}` : undefined);\n\n // Håndtere arrow-state\n useEffect(() => {\n if (showMenu) {\n setIsPointingDown(false);\n } else {\n setIsPointingDown(true);\n }\n }, [showMenu]);\n\n // Lukk meny med ESC\n useEffect(() => {\n const handleEscape = (e: globalThis.KeyboardEvent) => {\n if (e.key === \"Escape\" && showMenu) {\n setShowMenu(false);\n }\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"keydown\", handleEscape);\n }\n return () => {\n if (typeof window !== \"undefined\" && showMenu) {\n window.removeEventListener(\"keydown\", handleEscape);\n }\n };\n }, [setShowMenu, showMenu]);\n\n // Fokushåndtering\n const handleFocusPlacement = useCallback((isOpen: boolean) => {\n if (isOpen) {\n if (searchRef.current) {\n searchRef.current.focus();\n }\n } else {\n if (focusInsideRef.current && inputRef.current) {\n inputRef.current.focus();\n }\n }\n }, []);\n\n const handleFocus = useCallback(() => {\n if (!focusInsideRef.current) {\n if (onFocus) {\n onFocus({\n type: \"change\",\n target: {\n name,\n value: selectedValue?.[0].value || \"\",\n selectedOptions: selectedValue,\n },\n });\n }\n focusInsideRef.current = true;\n setShowMenu(true);\n }\n }, [onFocus, selectedValue, name]);\n\n const [dropdownRef] = useAnimatedHeight<HTMLDivElement>(showMenu, {\n onFirstVisible: handleFocusPlacement,\n onTransitionEnd: handleFocusPlacement,\n });\n\n useListNavigation({ ref: dropdownRef });\n\n const componentRootElementRef = useRef<HTMLDivElement>(null);\n\n const handleBlur = useCallback(\n (\n e: FocusEvent<\n HTMLDivElement | HTMLInputElement | HTMLButtonElement\n >,\n ) => {\n const componentRootElement = componentRootElementRef.current;\n const nextFocusIsInsideComponent =\n componentRootElement &&\n componentRootElement.contains(e.relatedTarget as Node);\n if (!nextFocusIsInsideComponent) {\n setSearchValue(\"\");\n\n if (onBlur) {\n onBlur({\n type: \"blur\",\n target: {\n name,\n value: selectedValue?.[0]?.value || \"\",\n selectedOptions: selectedValue,\n },\n });\n inputRef.current?.dispatchEvent(\n new Event(\"focusout\", { bubbles: true }),\n );\n }\n focusInsideRef.current = false;\n setShowMenu(false);\n }\n },\n [onBlur, name, selectedValue],\n );\n\n const handleMouseOver = useCallback((e: MouseEvent<HTMLButtonElement>) => {\n // Ved mouseOver på options flytter vi fokus til dem for å unngå \"dobbel fokus\"\n // der det ser ut som to forskjellige elementer er fokusert/hovered samtidig\n (e.target as HTMLButtonElement).focus({ preventScroll: true });\n }, []);\n\n // Tastaturnavigasjon\n const handleSearchOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n const listElement = dropdownRef.current;\n if (listElement) {\n listElement\n .querySelector<HTMLButtonElement>('[role=\"option\"]')\n ?.focus();\n }\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n setShowMenu(false);\n }\n\n if ((e.metaKey && e.key === \"a\") || (e.ctrlKey && e.key === \"a\")) {\n e.preventDefault();\n e.stopPropagation();\n const updatedSelectedValue = selectedValue.map((item) => ({\n ...item,\n isMarked: true,\n }));\n setMarked(true);\n setSelectedValue(updatedSelectedValue);\n } else if (e.key === \"Backspace\") {\n e.stopPropagation();\n setMarked(false);\n\n // Sjekk om selectedValue er markert\n const selectedValueIsMarked = selectedValue.some(\n (item) => item.isMarked,\n );\n\n if (selectedValueIsMarked) {\n const updatedSelectedValue = selectedValue.filter(\n (item) => !item.isMarked,\n );\n setSelectedValue(updatedSelectedValue);\n setSearchValue(\"\");\n } else if (selectedValue.length > 0 && searchValue === \"\") {\n // Hvis ingen items er markert, fjern siste valgte item\n onTagRemove(\n e,\n selectedValue[selectedValue.length - 1].value,\n );\n }\n }\n },\n [selectedValue, searchValue, dropdownRef, onTagRemove],\n );\n\n const handleOptionOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === \"Tab\") {\n if (searchRef.current) {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.shiftKey) {\n searchRef.current.focus();\n } else {\n setShowMenu(false);\n searchRef.current.focus();\n }\n }\n } else if (e.key === \"ArrowUp\") {\n if (dropdownRef.current && searchRef.current) {\n // Can't be based on index since the first item might be filtered out\n const firstVisible = dropdownRef.current.querySelector(\n '[role=\"option\"]:not([hidden])',\n );\n if (\n e.currentTarget.id === firstVisible?.id &&\n searchRef.current\n ) {\n searchRef.current.focus();\n }\n }\n }\n },\n [setShowMenu, dropdownRef],\n );\n\n const hasSelection = selectedValue.length >= 1;\n\n return (\n <InputGroup\n label={label}\n id={inputId}\n ref={componentRootElementRef}\n data-testid=\"jkl-combobox\"\n className={clsx(\"jkl-combobox\", className, {\n \"jkl-combobox--invalid\": !!errorLabel || invalid,\n \"jkl-combobox--menu-open\": showMenu,\n \"jkl-combobox--menu-closed\": !showMenu && hasSelection,\n })}\n labelProps={{\n id: labelId,\n ...labelProps,\n }}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n density={density}\n render={(inputProps) => (\n <div\n className={clsx(\"jkl-combobox__wrapper\", {\n \"jkl-combobox__wrapper--active-value\": hasSelection,\n })}\n style={{ width }}\n tabIndex={-1}\n onFocus={handleFocus}\n onBlur={handleBlur}\n >\n <div\n className=\"jkl-combobox__tags\"\n data-testid=\"jkl-combobox__tags\"\n >\n {selectedValue\n .map(getComboboxValuePair)\n .map((option) => (\n <Tag\n key={option.value}\n className={`jkl-tag ${\n marked && \"jkl-tag__marked\"\n }`}\n data-testid=\"jkl-tag\"\n dismissAction={{\n onClick: (e) => {\n if (searchRef.current) {\n searchRef.current.focus();\n }\n onTagRemove(e, option.value);\n },\n onBlur: handleBlur,\n label: `Fjern ${option.value}`,\n }}\n >\n {hasTagHover ? (\n <Tooltip key={option.value}>\n <TooltipTrigger>\n {\" \"}\n <span\n aria-hidden=\"true\"\n data-testid=\"jkl-tag__content\"\n >\n {option.tagLabel\n ? option.tagLabel\n : option.label}\n </span>\n </TooltipTrigger>\n <TooltipContent>\n {option.label}\n </TooltipContent>\n </Tooltip>\n ) : (\n <span\n aria-hidden=\"true\"\n data-testid=\"jkl-tag__content\"\n >\n {option.tagLabel\n ? option.tagLabel\n : option.label}\n </span>\n )}\n </Tag>\n ))}\n <input\n {...inputProps}\n className=\"jkl-combobox__search-input\"\n onChange={onSearch}\n data-testid=\"jkl-combobox__search-input\"\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleSearchOnKeyDown}\n value={searchValue}\n ref={searchRef}\n aria-controls={listId}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded={showMenu}\n placeholder={\n selectedValue.length > 0 ? \"\" : placeholder\n }\n autoComplete=\"off\"\n />\n </div>\n\n <div\n className=\"jkl-combobox__menu\"\n role=\"listbox\"\n ref={dropdownRef}\n id={listId}\n aria-labelledby={labelId}\n aria-multiselectable=\"true\"\n aria-activedescendant={activeDescendant}\n onFocus={handleFocus}\n onBlur={handleBlur}\n tabIndex={-1}\n >\n {options.map((option, i) => (\n <button\n key={`${listId}-${option.value}`}\n type=\"button\"\n id={`${listId}__${option.value}`}\n aria-selected={isSelected(option)}\n role=\"option\"\n value={option.value}\n onBlur={handleBlur}\n className={`jkl-combobox__option ${\n isSelected(option) &&\n \"jkl-combobox__option--selected\"\n }`}\n data-testid=\"jkl-combobox__option\"\n data-testautoid={`jkl-combobox__option-${i}`}\n onFocus={handleFocus}\n onKeyDown={handleOptionOnKeyDown}\n onClick={(e) => {\n setActiveDescendant(\n `${listId}__${option.value}`,\n ); // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role#required_javascript_features\n e.stopPropagation();\n onItemClick(option.value);\n setSearchValue(\"\");\n }}\n onMouseOver={handleMouseOver}\n >\n {option.description ? (\n <span>\n {option.label}\n <span className=\"jkl-combobox__option-description\">\n {option.description}\n </span>\n </span>\n ) : (\n option.label\n )}\n {isSelected(option) ? (\n <span>\n <CheckIcon />{\" \"}\n </span>\n ) : null}\n </button>\n ))}\n {noResults && (\n <div className=\"jkl-combobox__no-option\">\n {noMatchingOption}\n </div>\n )}\n </div>\n <div className=\"jkl-combobox__actions\">\n <IconButton\n id={buttonId}\n onFocus={handleFocus}\n onBlur={handleBlur}\n className=\"jkl-combobox__button\"\n data-testid=\"jkl-combobox__button\"\n aria-label={`${\n selectedValue.map((value) => value.label) ||\n \"Velg\"\n },${label}`}\n aria-expanded={showMenu}\n aria-controls={listId}\n role=\"button\"\n onClick={() => setShowMenu(true)}\n onMouseDown={(e) => {\n e.preventDefault();\n inputRef.current?.focus();\n }}\n >\n <ArrowVerticalAnimated\n pointingDown={isPointingDown}\n />\n </IconButton>\n </div>\n </div>\n )}\n />\n );\n};\nCombobox.displayName = \"Combobox\";\n"],"names":["getComboboxValuePair","item","value","label","Combobox","id","placeholder","items","onChange","onFocus","onBlur","noMatchingOption","labelProps","helpLabel","errorLabel","width","density","name","className","invalid","hasTagHover","listId","useId","generateSuffix","labelId","buttonId","inputId","selectedValue","setSelectedValue","useState","isPointingDown","setIsPointingDown","showMenu","setShowMenu","searchValue","setSearchValue","noResults","setNoResults","marked","setMarked","searchRef","useRef","inputRef","focusInsideRef","useEffect","current","focus","prev","isSelected","option","some","removeOption","useCallback","filter","onTagRemove","e","newValue","type","target","selectedOptions","stopPropagation","length","onItemClick","find","i","_a","onSearch","options","useMemo","filteredOptions","toLowerCase","indexOf","activeDescendant","setActiveDescendant","_b","handleEscape","key","window","addEventListener","removeEventListener","handleFocusPlacement","isOpen","handleFocus","dropdownRef","useAnimatedHeight","onFirstVisible","onTransitionEnd","useListNavigation","ref","componentRootElementRef","handleBlur","componentRootElement","contains","relatedTarget","dispatchEvent","Event","bubbles","handleMouseOver","preventScroll","handleSearchOnKeyDown","preventDefault","listElement","querySelector","metaKey","ctrlKey","updatedSelectedValue","map","isMarked","handleOptionOnKeyDown","shiftKey","firstVisible","currentTarget","hasSelection","jsx","InputGroup","clsx","render","inputProps","jsxs","style","tabIndex","children","Tag","dismissAction","onClick","Tooltip","TooltipTrigger","tagLabel","TooltipContent","onKeyDown","role","autoComplete","onMouseOver","description","CheckIcon","IconButton","onMouseDown","ArrowVerticalAnimated","pointingDown","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"Combobox.js","sources":["../../../../src/components/combobox/Combobox.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, {\n ChangeEvent,\n FC,\n FocusEvent,\n KeyboardEvent,\n MouseEvent,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { Density } from \"../../core/types.js\";\nimport { useAnimatedHeight } from \"../../hooks/useAnimatedHeight/useAnimatedHeight.js\";\nimport { useId } from \"../../hooks/useId/useId.js\";\nimport { useListNavigation } from \"../../hooks/useListNavigation/useListNavigation.js\";\nimport { ValuePair } from \"../../utilities/valuePair.js\";\nimport { ArrowVerticalAnimated } from \"../icon/icons/animated/ArrowVerticalAnimated.js\";\nimport { CheckIcon } from \"../icon/icons/CheckIcon.js\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { InputGroup, InputGroupProps } from \"../input-group/InputGroup.js\";\nimport { LabelProps } from \"../input-group/Label.js\";\nimport { Tag } from \"../tag/Tag.js\";\nimport { Tooltip } from \"../tooltip/Tooltip.js\";\nimport { TooltipContent } from \"../tooltip/TooltipContent.js\";\nimport { TooltipTrigger } from \"../tooltip/TooltipTrigger.js\";\n\nexport type ComboboxValuePair = ValuePair & {\n tagLabel?: string;\n isMarked?: boolean;\n};\n\nexport function getComboboxValuePair(\n item: string | ComboboxValuePair,\n): ComboboxValuePair {\n return typeof item === \"string\" ? { value: item, label: item } : item;\n}\n\ninterface PartialChangeEvent\n extends Partial<Omit<ChangeEvent<HTMLElement>, \"target\">> {\n type: \"change\" | \"blur\";\n target: {\n name: string;\n value: string;\n selectedOptions: Array<ValuePair>;\n };\n}\n\ntype ChangeEventHandler = (event: PartialChangeEvent) => void;\n\ninterface ComboboxProps extends InputGroupProps {\n id?: string;\n placeholder?: string;\n labelProps?: Omit<\n LabelProps,\n \"children\" | \"density\" | \"htmlFor\" | \"standAlone\"\n >;\n items: Array<ValuePair>;\n noMatchingOption?: string;\n label: string;\n name: string;\n value?: Array<ValuePair>;\n density?: Density;\n width?: string;\n helpLabel?: string;\n errorLabel?: string;\n className?: string;\n invalid?: boolean;\n hasTagHover?: boolean;\n onChange: ChangeEventHandler;\n onBlur?: ChangeEventHandler;\n onFocus?: ChangeEventHandler;\n}\n\nexport const Combobox: FC<ComboboxProps> = ({\n id,\n placeholder,\n items,\n onChange,\n onFocus,\n onBlur,\n value,\n label,\n noMatchingOption,\n labelProps,\n helpLabel,\n errorLabel,\n width,\n density,\n name,\n className,\n invalid,\n hasTagHover,\n}) => {\n const listId = useId(id || \"jkl-combobox\", { generateSuffix: !id });\n const labelId = `${listId}_label`;\n const buttonId = `${listId}_button`;\n const inputId = `${listId}_search-input`;\n\n const [selectedValue, setSelectedValue] = useState<\n Array<ComboboxValuePair>\n >(value || []);\n const [isPointingDown, setIsPointingDown] = useState<boolean>(true);\n const [showMenu, setShowMenu] = useState<boolean>(false);\n const [searchValue, setSearchValue] = useState<string>(\"\");\n const [noResults, setNoResults] = useState(false);\n const [marked, setMarked] = useState<boolean>(false);\n\n const searchRef = useRef<HTMLInputElement>(null);\n const inputRef = useRef<HTMLDivElement>(null);\n const focusInsideRef = useRef(false);\n\n useEffect(() => {\n setSearchValue(\"\");\n if (showMenu && searchRef.current) {\n searchRef.current.focus();\n }\n }, [showMenu]);\n\n useEffect(() => {\n setSelectedValue((prev) => value || prev);\n }, [value]);\n\n // Funksjon for å stile valgt element\n const isSelected = (option: ValuePair) => {\n if (!selectedValue) {\n return false;\n } else {\n return selectedValue.some((value) => value.value === option.value);\n }\n };\n\n // Fjerne ett eller flere valg\n const removeOption = useCallback(\n (option: string) => {\n return selectedValue.filter((value) => value.value !== option);\n },\n [selectedValue],\n );\n\n const onTagRemove = useCallback(\n (\n e:\n | React.MouseEvent<HTMLButtonElement, globalThis.MouseEvent>\n | React.KeyboardEvent<HTMLInputElement>,\n option: string,\n ) => {\n let newValue = removeOption(option);\n setSelectedValue(newValue);\n onChange({\n type: \"change\",\n target: { name, value: option, selectedOptions: newValue },\n });\n e.stopPropagation();\n\n if (newValue.length === 0) {\n setMarked(false);\n }\n },\n [removeOption, setSelectedValue, onChange, name, setMarked],\n );\n\n // Håndtere valgt verdi i listen\n const onItemClick = useCallback(\n (option: string) => {\n let newValue: Array<ValuePair>;\n\n if (selectedValue.some((value) => value.value === option)) {\n newValue = removeOption(option);\n } else {\n const item = items.find((i) => i.value === option);\n newValue = [...selectedValue, item as ValuePair];\n }\n searchRef.current?.focus();\n setSelectedValue(newValue);\n onChange({\n type: \"change\",\n target: { name, value: option, selectedOptions: newValue },\n });\n },\n [selectedValue, setSelectedValue, onChange, name, removeOption, items],\n );\n\n // Funksjon for søk\n const onSearch = (e: {\n target: { value: React.SetStateAction<string> };\n }) => {\n searchRef.current?.focus();\n setShowMenu(true);\n setSearchValue(e.target.value);\n };\n\n const options = useMemo(() => {\n if (!searchValue) {\n return items;\n }\n\n const filteredOptions = items.filter(\n (option) =>\n option.label.toLowerCase().indexOf(searchValue.toLowerCase()) >=\n 0,\n );\n\n setNoResults(filteredOptions.length === 0);\n\n return filteredOptions;\n }, [searchValue, items]);\n\n // Det første elementet i listen skal være aktivt fram til brukeren klikker på noe annet\n const [activeDescendant, setActiveDescendant] = useState<\n string | undefined\n >(options[0]?.value ? `${listId}-${options[0]?.value}` : undefined);\n\n // Håndtere arrow-state\n useEffect(() => {\n if (showMenu) {\n setIsPointingDown(false);\n } else {\n setIsPointingDown(true);\n }\n }, [showMenu]);\n\n // Lukk meny med ESC\n useEffect(() => {\n const handleEscape = (e: globalThis.KeyboardEvent) => {\n if (e.key === \"Escape\" && showMenu) {\n setShowMenu(false);\n }\n };\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"keydown\", handleEscape);\n }\n return () => {\n if (typeof window !== \"undefined\" && showMenu) {\n window.removeEventListener(\"keydown\", handleEscape);\n }\n };\n }, [setShowMenu, showMenu]);\n\n // Fokushåndtering\n const handleFocusPlacement = useCallback((isOpen: boolean) => {\n if (isOpen) {\n if (searchRef.current) {\n searchRef.current.focus();\n }\n } else {\n if (focusInsideRef.current && inputRef.current) {\n inputRef.current.focus();\n }\n }\n }, []);\n\n const handleFocus = useCallback(() => {\n if (!focusInsideRef.current) {\n if (onFocus) {\n onFocus({\n type: \"change\",\n target: {\n name,\n value: selectedValue?.[0].value || \"\",\n selectedOptions: selectedValue,\n },\n });\n }\n focusInsideRef.current = true;\n setShowMenu(true);\n }\n }, [onFocus, selectedValue, name]);\n\n const [dropdownRef] = useAnimatedHeight<HTMLDivElement>(showMenu, {\n onFirstVisible: handleFocusPlacement,\n onTransitionEnd: handleFocusPlacement,\n });\n\n useListNavigation({ ref: dropdownRef });\n\n const componentRootElementRef = useRef<HTMLDivElement>(null);\n\n const handleBlur = useCallback(\n (\n e: FocusEvent<\n HTMLDivElement | HTMLInputElement | HTMLButtonElement\n >,\n ) => {\n const componentRootElement = componentRootElementRef.current;\n const nextFocusIsInsideComponent =\n componentRootElement &&\n componentRootElement.contains(e.relatedTarget as Node);\n if (!nextFocusIsInsideComponent) {\n setSearchValue(\"\");\n\n if (onBlur) {\n onBlur({\n type: \"blur\",\n target: {\n name,\n value: selectedValue?.[0]?.value || \"\",\n selectedOptions: selectedValue,\n },\n });\n inputRef.current?.dispatchEvent(\n new Event(\"focusout\", { bubbles: true }),\n );\n }\n focusInsideRef.current = false;\n setShowMenu(false);\n }\n },\n [onBlur, name, selectedValue],\n );\n\n const handleMouseOver = useCallback((e: MouseEvent<HTMLButtonElement>) => {\n // Ved mouseOver på options flytter vi fokus til dem for å unngå \"dobbel fokus\"\n // der det ser ut som to forskjellige elementer er fokusert/hovered samtidig\n (e.target as HTMLButtonElement).focus({ preventScroll: true });\n }, []);\n\n // Tastaturnavigasjon\n const handleSearchOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n e.stopPropagation();\n const listElement = dropdownRef.current;\n if (listElement) {\n listElement\n .querySelector<HTMLButtonElement>('[role=\"option\"]')\n ?.focus();\n }\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n setShowMenu(false);\n }\n\n if ((e.metaKey && e.key === \"a\") || (e.ctrlKey && e.key === \"a\")) {\n e.preventDefault();\n e.stopPropagation();\n const updatedSelectedValue = selectedValue.map((item) => ({\n ...item,\n isMarked: true,\n }));\n setMarked(true);\n setSelectedValue(updatedSelectedValue);\n } else if (e.key === \"Backspace\") {\n e.stopPropagation();\n setMarked(false);\n\n // Sjekk om selectedValue er markert\n const selectedValueIsMarked = selectedValue.some(\n (item) => item.isMarked,\n );\n\n if (selectedValueIsMarked) {\n const updatedSelectedValue = selectedValue.filter(\n (item) => !item.isMarked,\n );\n setSelectedValue(updatedSelectedValue);\n setSearchValue(\"\");\n } else if (selectedValue.length > 0 && searchValue === \"\") {\n // Hvis ingen items er markert, fjern siste valgte item\n onTagRemove(\n e,\n selectedValue[selectedValue.length - 1].value,\n );\n }\n }\n },\n [selectedValue, searchValue, dropdownRef, onTagRemove],\n );\n\n const handleOptionOnKeyDown = useCallback(\n (e: KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === \"Tab\") {\n if (searchRef.current) {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.shiftKey) {\n searchRef.current.focus();\n } else {\n setShowMenu(false);\n searchRef.current.focus();\n }\n }\n } else if (e.key === \"ArrowUp\") {\n if (dropdownRef.current && searchRef.current) {\n // Can't be based on index since the first item might be filtered out\n const firstVisible = dropdownRef.current.querySelector(\n '[role=\"option\"]:not([hidden])',\n );\n if (\n e.currentTarget.id === firstVisible?.id &&\n searchRef.current\n ) {\n searchRef.current.focus();\n }\n }\n }\n },\n [setShowMenu, dropdownRef],\n );\n\n const hasSelection = selectedValue.length >= 1;\n\n return (\n <InputGroup\n label={label}\n id={inputId}\n ref={componentRootElementRef}\n data-testid=\"jkl-combobox\"\n className={clsx(\"jkl-combobox\", className, {\n \"jkl-combobox--invalid\": !!errorLabel || invalid,\n \"jkl-combobox--menu-open\": showMenu,\n \"jkl-combobox--menu-closed\": !showMenu && hasSelection,\n })}\n labelProps={{\n id: labelId,\n ...labelProps,\n }}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n density={density}\n render={(inputProps) => (\n <div\n className={clsx(\"jkl-combobox__wrapper\", {\n \"jkl-combobox__wrapper--active-value\": hasSelection,\n })}\n style={{ width }}\n tabIndex={-1}\n onFocus={handleFocus}\n onBlur={handleBlur}\n >\n <div\n className=\"jkl-combobox__tags\"\n data-testid=\"jkl-combobox__tags\"\n >\n {selectedValue\n .map(getComboboxValuePair)\n .map((option) => (\n <Tag\n key={option.value}\n className={`jkl-tag ${\n marked && \"jkl-tag__marked\"\n }`}\n data-testid=\"jkl-tag\"\n dismissAction={{\n onClick: (e) => {\n if (searchRef.current) {\n searchRef.current.focus();\n }\n onTagRemove(e, option.value);\n },\n onBlur: handleBlur,\n label: `Fjern ${option.value}`,\n }}\n >\n {hasTagHover ? (\n <Tooltip key={option.value}>\n <TooltipTrigger>\n {\" \"}\n <span\n aria-hidden=\"true\"\n data-testid=\"jkl-tag__content\"\n >\n {option.tagLabel\n ? option.tagLabel\n : option.label}\n </span>\n </TooltipTrigger>\n <TooltipContent>\n {option.label}\n </TooltipContent>\n </Tooltip>\n ) : (\n <span\n aria-hidden=\"true\"\n data-testid=\"jkl-tag__content\"\n >\n {option.tagLabel\n ? option.tagLabel\n : option.label}\n </span>\n )}\n </Tag>\n ))}\n <input\n {...inputProps}\n className=\"jkl-combobox__search-input\"\n onChange={onSearch}\n data-testid=\"jkl-combobox__search-input\"\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleSearchOnKeyDown}\n value={searchValue}\n ref={searchRef}\n aria-controls={listId}\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded={showMenu}\n placeholder={\n selectedValue.length > 0 ? \"\" : placeholder\n }\n autoComplete=\"off\"\n />\n </div>\n\n <div\n className=\"jkl-combobox__menu\"\n role=\"listbox\"\n ref={dropdownRef}\n id={listId}\n aria-labelledby={labelId}\n aria-multiselectable=\"true\"\n aria-activedescendant={activeDescendant}\n onFocus={handleFocus}\n onBlur={handleBlur}\n tabIndex={-1}\n >\n {options.map((option, i) => (\n <button\n key={`${listId}-${option.value}`}\n type=\"button\"\n id={`${listId}__${option.value}`}\n aria-selected={isSelected(option)}\n role=\"option\"\n value={option.value}\n onBlur={handleBlur}\n className={`jkl-combobox__option ${\n isSelected(option) &&\n \"jkl-combobox__option--selected\"\n }`}\n data-testid=\"jkl-combobox__option\"\n data-testautoid={`jkl-combobox__option-${i}`}\n onFocus={handleFocus}\n onKeyDown={handleOptionOnKeyDown}\n onClick={(e) => {\n setActiveDescendant(\n `${listId}__${option.value}`,\n ); // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role#required_javascript_features\n e.stopPropagation();\n onItemClick(option.value);\n setSearchValue(\"\");\n }}\n onMouseOver={handleMouseOver}\n >\n {option.description ? (\n <span>\n {option.label}\n <span className=\"jkl-combobox__option-description\">\n {option.description}\n </span>\n </span>\n ) : (\n option.label\n )}\n {isSelected(option) ? (\n <span>\n <CheckIcon />{\" \"}\n </span>\n ) : null}\n </button>\n ))}\n {noResults && (\n <div className=\"jkl-combobox__no-option\">\n {noMatchingOption}\n </div>\n )}\n </div>\n <div className=\"jkl-combobox__actions\">\n <IconButton\n id={buttonId}\n onFocus={handleFocus}\n onBlur={handleBlur}\n className=\"jkl-combobox__button\"\n data-testid=\"jkl-combobox__button\"\n aria-label={`${\n selectedValue.map((value) => value.label) ||\n \"Velg\"\n },${label}`}\n aria-expanded={showMenu}\n aria-controls={listId}\n role=\"button\"\n onClick={() => setShowMenu(true)}\n onMouseDown={(e) => {\n e.preventDefault();\n inputRef.current?.focus();\n }}\n >\n <ArrowVerticalAnimated\n pointingDown={isPointingDown}\n />\n </IconButton>\n </div>\n </div>\n )}\n />\n );\n};\nCombobox.displayName = \"Combobox\";\n"],"names":["getComboboxValuePair","item","value","label","Combobox","id","placeholder","items","onChange","onFocus","onBlur","noMatchingOption","labelProps","helpLabel","errorLabel","width","density","name","className","invalid","hasTagHover","listId","useId","generateSuffix","labelId","buttonId","inputId","selectedValue","setSelectedValue","useState","isPointingDown","setIsPointingDown","showMenu","setShowMenu","searchValue","setSearchValue","noResults","setNoResults","marked","setMarked","searchRef","useRef","inputRef","focusInsideRef","useEffect","current","focus","prev","isSelected","option","some","removeOption","useCallback","filter","onTagRemove","e","newValue","type","target","selectedOptions","stopPropagation","length","onItemClick","find","i","_a","onSearch","options","useMemo","filteredOptions","toLowerCase","indexOf","activeDescendant","setActiveDescendant","_b","handleEscape","key","window","addEventListener","removeEventListener","handleFocusPlacement","isOpen","handleFocus","dropdownRef","useAnimatedHeight","onFirstVisible","onTransitionEnd","useListNavigation","ref","componentRootElementRef","handleBlur","componentRootElement","contains","relatedTarget","dispatchEvent","Event","bubbles","handleMouseOver","preventScroll","handleSearchOnKeyDown","preventDefault","listElement","querySelector","metaKey","ctrlKey","updatedSelectedValue","map","isMarked","handleOptionOnKeyDown","shiftKey","firstVisible","currentTarget","hasSelection","jsx","InputGroup","clsx","render","inputProps","jsxs","style","tabIndex","children","Tag","dismissAction","onClick","Tooltip","TooltipTrigger","tagLabel","TooltipContent","onKeyDown","role","autoComplete","onMouseOver","description","CheckIcon","IconButton","onMouseDown","ArrowVerticalAnimated","pointingDown","displayName"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{jsx as o,jsxs as n}from"react/jsx-runtime";import{c as e}from"../../../clsx-BeLtu-UY.js";import{startOfDay as t}from"date-fns";import{forwardRef as r,useState as i,useRef as a,useCallback as s}from"react";import{flushSync as c}from"react-dom";import"../icon/Icon.js";import"../icon/icons/animated/ArrowVerticalAnimated.js";import"../icon/icons/animated/ArrowHorizontalAnimated.js";import"../icon/icons/animated/PlusRemoveAnimated.js";import"../icon/icons/ArrowDownIcon.js";import"../icon/icons/ArrowLeftIcon.js";import"../icon/icons/ArrowNorthEastIcon.js";import"../icon/icons/ArrowRightIcon.js";import"../icon/icons/ArrowUpIcon.js";import{CalendarIcon as l}from"../icon/icons/CalendarIcon.js";import"../icon/icons/CheckIcon.js";import"../icon/icons/ChevronDownIcon.js";import"../icon/icons/ChevronLeftIcon.js";import"../icon/icons/ChevronRightIcon.js";import"../icon/icons/ChevronUpIcon.js";import"../icon/icons/CloseIcon.js";import"../icon/icons/CopyIcon.js";import"../icon/icons/DotsIcon.js";import"../icon/icons/DragIcon.js";import"../icon/icons/ErrorIcon.js";import"../icon/icons/GreenCheckIcon.js";import"../icon/icons/HamburgerIcon.js";import"../icon/icons/InfoIcon.js";import"../icon/icons/LinkIcon.js";import"../icon/icons/PlusIcon.js";import"../icon/icons/QuestionIcon.js";import"../icon/icons/RedCrossIcon.js";import"../icon/icons/SearchIcon.js";import"../icon/icons/SuccessIcon.js";import"../icon/icons/WarningIcon.js";import"../icon/icons/MinusIcon.js";import"../icon/icons/ThumbDownIcon.js";import"../icon/icons/ThumbUpIcon.js";import"../icon/icons/TrashCanIcon.js";import"../icon/icons/PenIcon.js";import{IconButton as p}from"../icon-button/IconButton.js";import{InputGroup as u}from"../input-group/InputGroup.js";import{Popover as m}from"../popover/Popover.js";import{BaseTextInput as d}from"../text-input/BaseTextInput.js";import{Calendar as j}from"./internal/Calendar.js";import{getInitialDate as f}from"./internal/utils.js";import{parseDateString as I,formatInput as h}from"./utils.js";import{isWithinLowerBound as v,isWithinUpperBound as b}from"./validation.js";const k=r(((r,k)=>{const{"data-testautoid":D,id:g,className:w="",label:C="Velg dato",labelProps:y,defaultValue:L,defaultShow:P=!1,value:T,disableBeforeDate:A,disableAfterDate:E,yearsToShow:x,name:B,helpLabel:S,errorLabel:_,invalid:N,density:O,days:R,months:U,monthLabel:V,yearLabel:F,placeholder:W="dd.mm.åååå",width:G="11.25rem",onChange:H,onBlur:K,onFocus:M,onKeyDown:q,action:z,showCalendarLabel:Q="Åpne kalender",hideCalendarLabel:J="Lukk kalender",supportLabelProps:X,tooltipProps:Y,...Z}=r;"production"!==process.env.NODE_ENV&&T&&L&&console.warn("DatePicker må enten være controlled eller uncontrolled. Hvis du bruker defaultValue og value sammen vil defaultValue bli ignorert.");const $=I(A),oo=$?t($):void 0,no=I(E),eo=no?t(no):void 0,[to,ro]=i(f(T,L,oo,eo)),[io,ao]=i(null),[so,co]=i(P),lo=a(null),po=a(null),uo=a(null),mo=a(null),jo=s((o=>{mo.current=o,k&&("function"==typeof k?k(o):k.current=o)}),[mo,k]),fo=s((o=>{M&&po.current&&(po.current.contains(o.relatedTarget)||M(o,to,{error:io,value:o.target.value}))}),[M,to,io]),Io=s((o=>{K&&K(o,to,{error:io,value:o.target.value})}),[K,to,io]),ho=s((o=>{"Escape"===o.key&&(co(!1),o.preventDefault(),o.stopPropagation()),null!=z&&z.onKeyDown&&z.onKeyDown(o)}),[co,z]),vo=s((o=>{let n=null,e=null;if(o.target.value){const t=I(o.target.value);t?oo&&!v(t,oo)?e="OUTSIDE_LOWER_BOUND":eo&&!b(t,eo)?e="OUTSIDE_UPPER_BOUND":co(!1):e="WRONG_FORMAT",n=t||null}ao(e),ro(n),H&&H(o,n,{error:e,value:o.target.value})}),[H,ao,ro,co,oo,eo]),bo=s((o=>{c((()=>{co(!so)}));const n=lo.current,e=n&&n.querySelector('[aria-pressed="true"]');window.requestAnimationFrame((()=>e&&e.focus())),null!=z&&z.onClick&&z.onClick(o)}),[co,so,z,lo]),ko=s((({date:o})=>{if(co(!1),ro(o),mo.current){const n=mo.current;n.value=h(o);const e=document.createEvent("HTMLEvents");e.initEvent("input",!0,!1),n.dispatchEvent(e),n.focus(),H&&H(e,o,{error:null,value:n.value})}}),[co,ro,H]),Do=s((o=>{o.preventDefault(),co(!1),uo.current&&uo.current.focus()}),[co]);return o(u,{id:g,className:e("jkl-datepicker",w,{"jkl-datepicker--open":so}),...Z,ref:po,label:C,labelProps:y,density:O,helpLabel:S,errorLabel:_,supportLabelProps:X,tooltipProps:Y,render:e=>o(d,{ref:jo,"data-testid":"jkl-datepicker__input","data-testautoid":D,className:"jkl-datepicker__input",name:B,defaultValue:L,density:O,value:T,type:"text",placeholder:W,width:G,onFocus:fo,onBlur:Io,onChange:vo,actionButton:n(m,{positionReference:mo,open:so,onOpenChange:()=>co(!so),offset:8,children:[o(m.Trigger,{...z,"data-testid":"jkl-datepicker__trigger",className:"jkl-text-input-action-button",title:so?J:Q,tabIndex:0,onClick:bo,onKeyDown:ho,asChild:!0,children:o(p,{children:o(l,{})})}),o(m.Content,{initialFocus:-1,padding:24,children:o(j,{ref:lo,density:O,date:to,minDate:oo,maxDate:eo,days:R,months:U,monthLabel:V,yearLabel:F,yearsToShow:x,onDateSelected:ko,onTabOutside:Do})})]}),...e})})}));k.displayName="DatePicker";export{k as DatePicker};
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import{c as a}from"../../../clsx-BeLtu-UY.js";import{startOfDay as r}from"date-fns";import{forwardRef as o,useState as n,useRef as l,useCallback as s}from"react";import{flushSync as i}from"react-dom";import{CalendarIcon as u}from"../icon/icons/CalendarIcon.js";import{IconButton as d}from"../icon-button/IconButton.js";import{InputGroup as p}from"../input-group/InputGroup.js";import{Popover as c}from"../popover/Popover.js";import{BaseTextInput as m}from"../text-input/BaseTextInput.js";import{Calendar as f}from"./internal/Calendar.js";import{getInitialDate as v}from"./internal/utils.js";import{parseDateString as h,formatInput as b}from"./utils.js";import{isWithinLowerBound as k,isWithinUpperBound as D}from"./validation.js";const g=o(((o,g)=>{const{"data-testautoid":y,id:j,className:L="",label:w="Velg dato",labelProps:C,defaultValue:P,defaultShow:I=!1,value:x,disableBeforeDate:B,disableAfterDate:_,yearsToShow:E,name:O,helpLabel:T,errorLabel:N,invalid:S,density:R,days:U,months:V,monthLabel:F,yearLabel:K,placeholder:W="dd.mm.åååå",width:A="11.25rem",onChange:G,onBlur:q,onFocus:H,onKeyDown:M,action:z,showCalendarLabel:J="Åpne kalender",hideCalendarLabel:Q="Lukk kalender",supportLabelProps:X,tooltipProps:Y,...Z}=o;"production"!==process.env.NODE_ENV&&x&&P&&console.warn("DatePicker må enten være controlled eller uncontrolled. Hvis du bruker defaultValue og value sammen vil defaultValue bli ignorert.");const $=h(B),ee=$?r($):void 0,te=h(_),ae=te?r(te):void 0,[re,oe]=n(v(x,P,ee,ae)),[ne,le]=n(null),[se,ie]=n(I),ue=l(null),de=l(null),pe=l(null),ce=l(null),me=s((e=>{ce.current=e,g&&("function"==typeof g?g(e):g.current=e)}),[ce,g]),fe=s((e=>{H&&de.current&&(de.current.contains(e.relatedTarget)||H(e,re,{error:ne,value:e.target.value}))}),[H,re,ne]),ve=s((e=>{q&&q(e,re,{error:ne,value:e.target.value})}),[q,re,ne]),he=s((e=>{"Escape"===e.key&&(ie(!1),e.preventDefault(),e.stopPropagation()),null!=z&&z.onKeyDown&&z.onKeyDown(e)}),[ie,z]),be=s((e=>{let t=null,a=null;if(e.target.value){const r=h(e.target.value);r?ee&&!k(r,ee)?a="OUTSIDE_LOWER_BOUND":ae&&!D(r,ae)?a="OUTSIDE_UPPER_BOUND":ie(!1):a="WRONG_FORMAT",t=r||null}le(a),oe(t),G&&G(e,t,{error:a,value:e.target.value})}),[G,le,oe,ie,ee,ae]),ke=s((e=>{i((()=>{ie(!se)}));const t=ue.current,a=t&&t.querySelector('[aria-pressed="true"]');window.requestAnimationFrame((()=>a&&a.focus())),null!=z&&z.onClick&&z.onClick(e)}),[ie,se,z,ue]),De=s((({date:e})=>{if(ie(!1),oe(e),ce.current){const t=ce.current;t.value=b(e);const a=document.createEvent("HTMLEvents");a.initEvent("input",!0,!1),t.dispatchEvent(a),t.focus(),G&&G(a,e,{error:null,value:t.value})}}),[ie,oe,G]),ge=s((e=>{e.preventDefault(),ie(!1),pe.current&&pe.current.focus()}),[ie]);return e(p,{id:j,className:a("jkl-datepicker",L,{"jkl-datepicker--open":se}),...Z,ref:de,label:w,labelProps:C,density:R,helpLabel:T,errorLabel:N,supportLabelProps:X,tooltipProps:Y,render:a=>e(m,{ref:me,"data-testid":"jkl-datepicker__input","data-testautoid":y,className:"jkl-datepicker__input",name:O,defaultValue:P,density:R,value:x,type:"text",placeholder:W,width:A,onFocus:fe,onBlur:ve,onChange:be,actionButton:t(c,{positionReference:ce,open:se,onOpenChange:()=>ie(!se),offset:8,children:[e(c.Trigger,{...z,"data-testid":"jkl-datepicker__trigger",className:"jkl-text-input-action-button",title:se?Q:J,tabIndex:0,onClick:ke,onKeyDown:he,asChild:!0,children:e(d,{children:e(u,{})})}),e(c.Content,{initialFocus:-1,padding:24,children:e(f,{ref:ue,density:R,date:re,minDate:ee,maxDate:ae,days:U,months:V,monthLabel:F,yearLabel:K,yearsToShow:E,onDateSelected:De,onTabOutside:ge})})]}),...a})})}));g.displayName="DatePicker";export{g as DatePicker};
2
2
  //# sourceMappingURL=DatePicker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker.js","sources":["../../../../src/components/datepicker/DatePicker.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { startOfDay } from \"date-fns\";\nimport React, {\n ChangeEvent,\n FocusEvent,\n KeyboardEvent,\n MouseEvent,\n forwardRef,\n useCallback,\n useRef,\n useState,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { CalendarIcon } from \"../icon/index.js\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport Popover from \"../popover/Popover.js\";\nimport { BaseTextInput } from \"../text-input/BaseTextInput.js\";\nimport { Calendar } from \"./internal/Calendar.js\";\nimport { DateInfo, getInitialDate } from \"./internal/utils.js\";\nimport { DatePickerProps, DateValidationError } from \"./types.js\";\nimport { formatInput, parseDateString } from \"./utils.js\";\nimport { isWithinLowerBound, isWithinUpperBound } from \"./validation.js\";\n\nexport const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(\n (props, forwardedInputRef) => {\n const {\n \"data-testautoid\": testAutoId,\n id,\n className = \"\",\n label = \"Velg dato\",\n labelProps,\n defaultValue,\n defaultShow = false,\n value,\n disableBeforeDate: disableBefore,\n disableAfterDate: disableAfter,\n yearsToShow,\n name,\n helpLabel,\n errorLabel,\n invalid,\n density,\n days,\n months,\n monthLabel,\n yearLabel,\n placeholder = \"dd.mm.åååå\",\n width = \"11.25rem\",\n onChange,\n onBlur,\n onFocus,\n onKeyDown,\n action,\n showCalendarLabel = \"Åpne kalender\",\n hideCalendarLabel = \"Lukk kalender\",\n supportLabelProps,\n tooltipProps,\n ...rest\n } = props;\n\n if (process.env.NODE_ENV !== \"production\" && value && defaultValue) {\n console.warn(\n \"DatePicker må enten være controlled eller uncontrolled. Hvis du bruker defaultValue og value sammen vil defaultValue bli ignorert.\",\n );\n }\n /// Input state\n\n const disableBeforeDate = parseDateString(disableBefore);\n const minDate = disableBeforeDate\n ? startOfDay(disableBeforeDate)\n : undefined;\n const disableAfterDate = parseDateString(disableAfter);\n const maxDate = disableAfterDate\n ? startOfDay(disableAfterDate)\n : undefined;\n\n const [date, setDate] = useState(\n getInitialDate(value, defaultValue, minDate, maxDate),\n );\n const [error, setError] = useState<DateValidationError | null>(null);\n\n /// Calendar state\n\n const [showCalendar, setShowCalendar] = useState(defaultShow);\n\n const calendarRef = useRef<HTMLDivElement>(null);\n const datepickerRef = useRef<HTMLDivElement>(null);\n\n /// Input events\n\n const iconButtonRef = useRef<HTMLButtonElement | null>(null);\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Hjelper for å gjøre det enklere å både forwarde refen men også bruke den selv internt\n const unifiedInputRef = useCallback(\n (instance: HTMLInputElement | null) => {\n inputRef.current = instance;\n if (forwardedInputRef) {\n if (typeof forwardedInputRef === \"function\") {\n forwardedInputRef(instance);\n } else {\n forwardedInputRef.current = instance;\n }\n }\n },\n [inputRef, forwardedInputRef],\n );\n\n const handleFocus = useCallback(\n (e: FocusEvent<HTMLInputElement>) => {\n if (!onFocus || !datepickerRef.current) {\n return;\n }\n\n const nextFocusIsInside = datepickerRef.current.contains(\n e.relatedTarget as Node,\n );\n if (!nextFocusIsInside) {\n onFocus(e, date, { error, value: e.target.value });\n }\n },\n [onFocus, date, error],\n );\n\n const handleBlur = useCallback(\n (e: FocusEvent<HTMLInputElement>) => {\n if (onBlur) {\n onBlur(e, date, { error, value: e.target.value });\n }\n },\n [onBlur, date, error],\n );\n\n const handleKeyDownAction = useCallback(\n (e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === \"Escape\") {\n setShowCalendar(false);\n e.preventDefault();\n e.stopPropagation();\n }\n\n if (action?.onKeyDown) {\n action.onKeyDown(e);\n }\n },\n [setShowCalendar, action],\n );\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n let nextDate: Date | null = null;\n let nextError: DateValidationError | null = null;\n\n if (e.target.value) {\n const val = parseDateString(e.target.value);\n if (!val) {\n nextError = \"WRONG_FORMAT\";\n } else if (minDate && !isWithinLowerBound(val, minDate)) {\n nextError = \"OUTSIDE_LOWER_BOUND\";\n } else if (maxDate && !isWithinUpperBound(val, maxDate)) {\n nextError = \"OUTSIDE_UPPER_BOUND\";\n } else {\n setShowCalendar(false);\n }\n nextDate = val || null;\n }\n\n setError(nextError);\n setDate(nextDate);\n\n if (onChange) {\n onChange(e, nextDate, {\n error: nextError,\n value: e.target.value,\n });\n }\n },\n [onChange, setError, setDate, setShowCalendar, minDate, maxDate],\n );\n\n /// Calendar events\n\n const clickCalendar = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n flushSync(() => {\n setShowCalendar(!showCalendar);\n });\n\n const calendarEl = calendarRef.current;\n const button =\n calendarEl &&\n (calendarEl.querySelector(\n '[aria-pressed=\"true\"]',\n ) as HTMLButtonElement);\n // Make sure the popover-modal is correctly positioned before focusing a button\n // so we avoid accidentally scrolling to the top of the page\n window.requestAnimationFrame(() => button && button.focus());\n\n if (action?.onClick) {\n action.onClick(e);\n }\n },\n [setShowCalendar, showCalendar, action, calendarRef],\n );\n\n const handleClickCalendarDay = useCallback(\n ({ date }: DateInfo) => {\n setShowCalendar(false);\n setDate(date);\n\n if (inputRef.current) {\n const node = inputRef.current;\n\n node.value = formatInput(date);\n\n // Simulér et change-event så APIet blir så likt som mulig en endring av inputfeltet\n const event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"input\", true, false);\n node.dispatchEvent(event);\n\n node.focus();\n\n if (onChange) {\n // Det er ikke helt sant at dette er et React.SyntheticEvent, men it's fine – probably?\n // Den har tingene man kan forvente, men hvis du gjør serdeles fancy ting med events\n // så kan det hende du må utvide denne for å dekke behovet ditt.\n onChange(\n event as unknown as ChangeEvent<HTMLInputElement>,\n date,\n {\n error: null,\n value: node.value,\n },\n );\n }\n }\n },\n [setShowCalendar, setDate, onChange],\n );\n\n const handleTabOutsideCalendar = useCallback(\n (e: KeyboardEvent) => {\n e.preventDefault();\n setShowCalendar(false);\n iconButtonRef.current && iconButtonRef.current.focus();\n },\n [setShowCalendar],\n );\n\n return (\n <InputGroup\n id={id}\n className={clsx(\"jkl-datepicker\", className, {\n \"jkl-datepicker--open\": showCalendar,\n })}\n {...rest}\n ref={datepickerRef}\n label={label}\n labelProps={labelProps}\n density={density}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n supportLabelProps={supportLabelProps}\n tooltipProps={tooltipProps}\n render={(inputProps) => (\n <BaseTextInput\n ref={unifiedInputRef}\n data-testid=\"jkl-datepicker__input\"\n data-testautoid={testAutoId}\n className=\"jkl-datepicker__input\"\n name={name}\n defaultValue={defaultValue}\n density={density}\n value={value}\n type=\"text\"\n placeholder={placeholder}\n width={width}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n actionButton={\n <Popover\n positionReference={inputRef}\n open={showCalendar}\n onOpenChange={() =>\n setShowCalendar(!showCalendar)\n }\n offset={8}\n >\n <Popover.Trigger\n {...action}\n data-testid=\"jkl-datepicker__trigger\"\n className=\"jkl-text-input-action-button\"\n title={\n showCalendar\n ? hideCalendarLabel\n : showCalendarLabel\n }\n tabIndex={0}\n onClick={clickCalendar}\n onKeyDown={handleKeyDownAction}\n asChild\n >\n <IconButton>\n <CalendarIcon />\n </IconButton>\n </Popover.Trigger>\n <Popover.Content initialFocus={-1} padding={24}>\n <Calendar\n ref={calendarRef}\n density={density}\n date={date}\n minDate={minDate}\n maxDate={maxDate}\n days={days}\n months={months}\n monthLabel={monthLabel}\n yearLabel={yearLabel}\n yearsToShow={yearsToShow}\n onDateSelected={handleClickCalendarDay}\n onTabOutside={handleTabOutsideCalendar}\n />\n </Popover.Content>\n </Popover>\n }\n {...inputProps}\n />\n )}\n />\n );\n },\n);\n\nDatePicker.displayName = \"DatePicker\";\n"],"names":["DatePicker","forwardRef","props","forwardedInputRef","testAutoId","id","className","label","labelProps","defaultValue","defaultShow","value","disableBeforeDate","disableBefore","disableAfterDate","disableAfter","yearsToShow","name","helpLabel","errorLabel","invalid","density","days","months","monthLabel","yearLabel","placeholder","width","onChange","onBlur","onFocus","onKeyDown","action","showCalendarLabel","hideCalendarLabel","supportLabelProps","tooltipProps","rest","process","env","NODE_ENV","console","warn","parseDateString","minDate","startOfDay","maxDate","date","setDate","useState","getInitialDate","error","setError","showCalendar","setShowCalendar","calendarRef","useRef","datepickerRef","iconButtonRef","inputRef","unifiedInputRef","useCallback","instance","current","handleFocus","e","contains","relatedTarget","target","handleBlur","handleKeyDownAction","key","preventDefault","stopPropagation","handleChange","nextDate","nextError","val","isWithinLowerBound","isWithinUpperBound","clickCalendar","flushSync","calendarEl","button","querySelector","window","requestAnimationFrame","focus","onClick","handleClickCalendarDay","node","formatInput","event","document","createEvent","initEvent","dispatchEvent","handleTabOutsideCalendar","jsx","InputGroup","clsx","ref","render","inputProps","BaseTextInput","type","actionButton","jsxs","Popover","positionReference","open","onOpenChange","offset","children","Trigger","title","tabIndex","asChild","IconButton","CalendarIcon","Content","initialFocus","padding","Calendar","onDateSelected","onTabOutside","displayName"],"mappings":"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"}
1
+ {"version":3,"file":"DatePicker.js","sources":["../../../../src/components/datepicker/DatePicker.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport { startOfDay } from \"date-fns\";\nimport React, {\n ChangeEvent,\n FocusEvent,\n KeyboardEvent,\n MouseEvent,\n forwardRef,\n useCallback,\n useRef,\n useState,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { CalendarIcon } from \"../icon/icons/CalendarIcon.js\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { InputGroup } from \"../input-group/InputGroup.js\";\nimport Popover from \"../popover/Popover.js\";\nimport { BaseTextInput } from \"../text-input/BaseTextInput.js\";\nimport { Calendar } from \"./internal/Calendar.js\";\nimport { DateInfo, getInitialDate } from \"./internal/utils.js\";\nimport { DatePickerProps, DateValidationError } from \"./types.js\";\nimport { formatInput, parseDateString } from \"./utils.js\";\nimport { isWithinLowerBound, isWithinUpperBound } from \"./validation.js\";\n\nexport const DatePicker = forwardRef<HTMLInputElement, DatePickerProps>(\n (props, forwardedInputRef) => {\n const {\n \"data-testautoid\": testAutoId,\n id,\n className = \"\",\n label = \"Velg dato\",\n labelProps,\n defaultValue,\n defaultShow = false,\n value,\n disableBeforeDate: disableBefore,\n disableAfterDate: disableAfter,\n yearsToShow,\n name,\n helpLabel,\n errorLabel,\n invalid,\n density,\n days,\n months,\n monthLabel,\n yearLabel,\n placeholder = \"dd.mm.åååå\",\n width = \"11.25rem\",\n onChange,\n onBlur,\n onFocus,\n onKeyDown,\n action,\n showCalendarLabel = \"Åpne kalender\",\n hideCalendarLabel = \"Lukk kalender\",\n supportLabelProps,\n tooltipProps,\n ...rest\n } = props;\n\n if (process.env.NODE_ENV !== \"production\" && value && defaultValue) {\n console.warn(\n \"DatePicker må enten være controlled eller uncontrolled. Hvis du bruker defaultValue og value sammen vil defaultValue bli ignorert.\",\n );\n }\n /// Input state\n\n const disableBeforeDate = parseDateString(disableBefore);\n const minDate = disableBeforeDate\n ? startOfDay(disableBeforeDate)\n : undefined;\n const disableAfterDate = parseDateString(disableAfter);\n const maxDate = disableAfterDate\n ? startOfDay(disableAfterDate)\n : undefined;\n\n const [date, setDate] = useState(\n getInitialDate(value, defaultValue, minDate, maxDate),\n );\n const [error, setError] = useState<DateValidationError | null>(null);\n\n /// Calendar state\n\n const [showCalendar, setShowCalendar] = useState(defaultShow);\n\n const calendarRef = useRef<HTMLDivElement>(null);\n const datepickerRef = useRef<HTMLDivElement>(null);\n\n /// Input events\n\n const iconButtonRef = useRef<HTMLButtonElement | null>(null);\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Hjelper for å gjøre det enklere å både forwarde refen men også bruke den selv internt\n const unifiedInputRef = useCallback(\n (instance: HTMLInputElement | null) => {\n inputRef.current = instance;\n if (forwardedInputRef) {\n if (typeof forwardedInputRef === \"function\") {\n forwardedInputRef(instance);\n } else {\n forwardedInputRef.current = instance;\n }\n }\n },\n [inputRef, forwardedInputRef],\n );\n\n const handleFocus = useCallback(\n (e: FocusEvent<HTMLInputElement>) => {\n if (!onFocus || !datepickerRef.current) {\n return;\n }\n\n const nextFocusIsInside = datepickerRef.current.contains(\n e.relatedTarget as Node,\n );\n if (!nextFocusIsInside) {\n onFocus(e, date, { error, value: e.target.value });\n }\n },\n [onFocus, date, error],\n );\n\n const handleBlur = useCallback(\n (e: FocusEvent<HTMLInputElement>) => {\n if (onBlur) {\n onBlur(e, date, { error, value: e.target.value });\n }\n },\n [onBlur, date, error],\n );\n\n const handleKeyDownAction = useCallback(\n (e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (e.key === \"Escape\") {\n setShowCalendar(false);\n e.preventDefault();\n e.stopPropagation();\n }\n\n if (action?.onKeyDown) {\n action.onKeyDown(e);\n }\n },\n [setShowCalendar, action],\n );\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n let nextDate: Date | null = null;\n let nextError: DateValidationError | null = null;\n\n if (e.target.value) {\n const val = parseDateString(e.target.value);\n if (!val) {\n nextError = \"WRONG_FORMAT\";\n } else if (minDate && !isWithinLowerBound(val, minDate)) {\n nextError = \"OUTSIDE_LOWER_BOUND\";\n } else if (maxDate && !isWithinUpperBound(val, maxDate)) {\n nextError = \"OUTSIDE_UPPER_BOUND\";\n } else {\n setShowCalendar(false);\n }\n nextDate = val || null;\n }\n\n setError(nextError);\n setDate(nextDate);\n\n if (onChange) {\n onChange(e, nextDate, {\n error: nextError,\n value: e.target.value,\n });\n }\n },\n [onChange, setError, setDate, setShowCalendar, minDate, maxDate],\n );\n\n /// Calendar events\n\n const clickCalendar = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n flushSync(() => {\n setShowCalendar(!showCalendar);\n });\n\n const calendarEl = calendarRef.current;\n const button =\n calendarEl &&\n (calendarEl.querySelector(\n '[aria-pressed=\"true\"]',\n ) as HTMLButtonElement);\n // Make sure the popover-modal is correctly positioned before focusing a button\n // so we avoid accidentally scrolling to the top of the page\n window.requestAnimationFrame(() => button && button.focus());\n\n if (action?.onClick) {\n action.onClick(e);\n }\n },\n [setShowCalendar, showCalendar, action, calendarRef],\n );\n\n const handleClickCalendarDay = useCallback(\n ({ date }: DateInfo) => {\n setShowCalendar(false);\n setDate(date);\n\n if (inputRef.current) {\n const node = inputRef.current;\n\n node.value = formatInput(date);\n\n // Simulér et change-event så APIet blir så likt som mulig en endring av inputfeltet\n const event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"input\", true, false);\n node.dispatchEvent(event);\n\n node.focus();\n\n if (onChange) {\n // Det er ikke helt sant at dette er et React.SyntheticEvent, men it's fine – probably?\n // Den har tingene man kan forvente, men hvis du gjør serdeles fancy ting med events\n // så kan det hende du må utvide denne for å dekke behovet ditt.\n onChange(\n event as unknown as ChangeEvent<HTMLInputElement>,\n date,\n {\n error: null,\n value: node.value,\n },\n );\n }\n }\n },\n [setShowCalendar, setDate, onChange],\n );\n\n const handleTabOutsideCalendar = useCallback(\n (e: KeyboardEvent) => {\n e.preventDefault();\n setShowCalendar(false);\n iconButtonRef.current && iconButtonRef.current.focus();\n },\n [setShowCalendar],\n );\n\n return (\n <InputGroup\n id={id}\n className={clsx(\"jkl-datepicker\", className, {\n \"jkl-datepicker--open\": showCalendar,\n })}\n {...rest}\n ref={datepickerRef}\n label={label}\n labelProps={labelProps}\n density={density}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n supportLabelProps={supportLabelProps}\n tooltipProps={tooltipProps}\n render={(inputProps) => (\n <BaseTextInput\n ref={unifiedInputRef}\n data-testid=\"jkl-datepicker__input\"\n data-testautoid={testAutoId}\n className=\"jkl-datepicker__input\"\n name={name}\n defaultValue={defaultValue}\n density={density}\n value={value}\n type=\"text\"\n placeholder={placeholder}\n width={width}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n actionButton={\n <Popover\n positionReference={inputRef}\n open={showCalendar}\n onOpenChange={() =>\n setShowCalendar(!showCalendar)\n }\n offset={8}\n >\n <Popover.Trigger\n {...action}\n data-testid=\"jkl-datepicker__trigger\"\n className=\"jkl-text-input-action-button\"\n title={\n showCalendar\n ? hideCalendarLabel\n : showCalendarLabel\n }\n tabIndex={0}\n onClick={clickCalendar}\n onKeyDown={handleKeyDownAction}\n asChild\n >\n <IconButton>\n <CalendarIcon />\n </IconButton>\n </Popover.Trigger>\n <Popover.Content initialFocus={-1} padding={24}>\n <Calendar\n ref={calendarRef}\n density={density}\n date={date}\n minDate={minDate}\n maxDate={maxDate}\n days={days}\n months={months}\n monthLabel={monthLabel}\n yearLabel={yearLabel}\n yearsToShow={yearsToShow}\n onDateSelected={handleClickCalendarDay}\n onTabOutside={handleTabOutsideCalendar}\n />\n </Popover.Content>\n </Popover>\n }\n {...inputProps}\n />\n )}\n />\n );\n },\n);\n\nDatePicker.displayName = \"DatePicker\";\n"],"names":["DatePicker","forwardRef","props","forwardedInputRef","testAutoId","id","className","label","labelProps","defaultValue","defaultShow","value","disableBeforeDate","disableBefore","disableAfterDate","disableAfter","yearsToShow","name","helpLabel","errorLabel","invalid","density","days","months","monthLabel","yearLabel","placeholder","width","onChange","onBlur","onFocus","onKeyDown","action","showCalendarLabel","hideCalendarLabel","supportLabelProps","tooltipProps","rest","process","env","NODE_ENV","console","warn","parseDateString","minDate","startOfDay","maxDate","date","setDate","useState","getInitialDate","error","setError","showCalendar","setShowCalendar","calendarRef","useRef","datepickerRef","iconButtonRef","inputRef","unifiedInputRef","useCallback","instance","current","handleFocus","e","contains","relatedTarget","target","handleBlur","handleKeyDownAction","key","preventDefault","stopPropagation","handleChange","nextDate","nextError","val","isWithinLowerBound","isWithinUpperBound","clickCalendar","flushSync","calendarEl","button","querySelector","window","requestAnimationFrame","focus","onClick","handleClickCalendarDay","node","formatInput","event","document","createEvent","initEvent","dispatchEvent","handleTabOutsideCalendar","jsx","InputGroup","clsx","ref","render","inputProps","BaseTextInput","type","actionButton","jsxs","Popover","positionReference","open","onOpenChange","offset","children","Trigger","title","tabIndex","asChild","IconButton","CalendarIcon","Content","initialFocus","padding","Calendar","onDateSelected","onTabOutside","displayName"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import{forwardRef as n,useReducer as a,useEffect as o,useCallback as r,useRef as c}from"react";import{flushSync as i}from"react-dom";import{useId as s}from"../../../hooks/useId/useId.js";import"../../icon/Icon.js";import"../../icon/icons/animated/ArrowVerticalAnimated.js";import"../../icon/icons/animated/ArrowHorizontalAnimated.js";import"../../icon/icons/animated/PlusRemoveAnimated.js";import"../../icon/icons/ArrowDownIcon.js";import{ArrowLeftIcon as l}from"../../icon/icons/ArrowLeftIcon.js";import"../../icon/icons/ArrowNorthEastIcon.js";import{ArrowRightIcon as d}from"../../icon/icons/ArrowRightIcon.js";import"../../icon/icons/ArrowUpIcon.js";import"../../icon/icons/CalendarIcon.js";import"../../icon/icons/CheckIcon.js";import{ChevronDownIcon as u}from"../../icon/icons/ChevronDownIcon.js";import"../../icon/icons/ChevronLeftIcon.js";import"../../icon/icons/ChevronRightIcon.js";import"../../icon/icons/ChevronUpIcon.js";import"../../icon/icons/CloseIcon.js";import"../../icon/icons/CopyIcon.js";import"../../icon/icons/DotsIcon.js";import"../../icon/icons/DragIcon.js";import"../../icon/icons/ErrorIcon.js";import"../../icon/icons/GreenCheckIcon.js";import"../../icon/icons/HamburgerIcon.js";import"../../icon/icons/InfoIcon.js";import"../../icon/icons/LinkIcon.js";import"../../icon/icons/PlusIcon.js";import"../../icon/icons/QuestionIcon.js";import"../../icon/icons/RedCrossIcon.js";import"../../icon/icons/SearchIcon.js";import"../../icon/icons/SuccessIcon.js";import"../../icon/icons/WarningIcon.js";import"../../icon/icons/MinusIcon.js";import"../../icon/icons/ThumbDownIcon.js";import"../../icon/icons/ThumbUpIcon.js";import"../../icon/icons/TrashCanIcon.js";import"../../icon/icons/PenIcon.js";import{calendarReducer as m,calendarInitializer as h}from"./calendarReducer.js";import{useCalendar as p}from"./useCalendar.js";import{getInitialDateShown as g,isBackDisabled as f,subtractMonth as j,isForwardDisabled as b,addMonth as v,getYearSelectOptions as w,getMonthSelectOptions as k,DEFAULT_YEARS_TO_SHOW as D}from"./utils.js";const I=["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],y=["man","tir","ons","tor","fre","lør","søn"],A=n(((n,A)=>{const{date:_,defaultSelected:M,density:S,minDate:C,maxDate:F,days:N=y,months:E=I,monthLabel:Y="Velg måned",yearLabel:x="Velg år",yearsToShow:O=D,onTabOutside:T,...$}=n,R=s("jkl-calendar"),[{offset:L,selectedDate:q,shownDate:P},U]=a(m,g(_,M,C,F),h),K=P.getMonth(),H=P.getFullYear();o((()=>{U({type:"SET_SELECTED_DATE",newDate:g(_,M,C,F)})}),[_,M,C,F]);const J=r((e=>{U({type:"SET_OFFSET",newOffset:e})}),[]),{calendars:V,getBackProps:W,getDateProps:z,getForwardProps:B,handleOffsetChanged:G}=p({date:q,selected:q,minDate:C,maxDate:F,offset:L,onOffsetChanged:J,firstDayOfWeek:1,...$}),Q=c(null),X=r((e=>{if(!Q.current)return;const t=document.activeElement,n=Q.current.querySelectorAll('button.jkl-calendar-date-button:not([data-adjacent="true"]'),a=async e=>{null==t||t.setAttribute("tabindex","-1"),e.setAttribute("tabindex","0"),e.focus()};n.forEach(((o,r)=>{const c=r+e;if(o==t)if(c<=n.length-1&&c>=0)a(n[c]);else if(e<0){if(f({calendars:V,minDate:C})||(i((()=>{G(L-j({calendars:V,offset:1,minDate:C}))})),!Q.current))return;const e=Q.current.querySelectorAll('button.jkl-calendar-date-button:not([data-adjacent="true"]');e[e.length+c]&&(e[0].setAttribute("tabindex","-1"),a(e[e.length+c]))}else{if(b({calendars:V,maxDate:F})||(i((()=>{G(L+v({calendars:V,offset:1,maxDate:F}))})),!Q.current))return;const e=Q.current.querySelectorAll('button.jkl-calendar-date-button:not([data-adjacent="true"]');e[c-n.length]&&(e[0].setAttribute("tabindex","-1"),a(e[c-n.length]))}}))}),[G,Q,L,V,F,C]),Z=r((e=>{switch(e.key){case"ArrowUp":X(-7),e.preventDefault();break;case"ArrowRight":X(1),e.preventDefault();break;case"ArrowDown":X(7),e.preventDefault();break;case"ArrowLeft":X(-1),e.preventDefault()}}),[X]),ee=r((e=>{var t;if("Tab"!==e.key)return;const n=null==(t=Q.current)?void 0:t.querySelectorAll('button:not([disabled]):not([tabindex="-1"]), select');if(!n)return;const a=n[0],o=n[n.length-1];e.shiftKey||document.activeElement!==o?e.shiftKey&&document.activeElement===a&&(o.focus(),e.preventDefault()):(a.focus(),e.preventDefault())}),[]),te=r((e=>{const{date:t,selected:n,selectable:a,prevMonth:o,nextMonth:r}=e;return!!a&&!(!n&&t.toString()!==(null==C?void 0:C.toString())&&(o||r||P.getFullYear()!==t.getFullYear()||q.getMonth()===t.getMonth()||1!==t.getDate()))}),[P,C,q]),ne=r((()=>{C&&P.getFullYear()-C.getFullYear()==0&&P.getMonth()-C.getMonth()==1?document.querySelectorAll(".jkl-calendar-navigation__arrow")[1].focus():F&&F.getFullYear()-P.getFullYear()==0&&F.getMonth()-P.getMonth()==1&&document.querySelectorAll(".jkl-calendar-navigation__arrow")[0].focus()}),[C,F,P]),ae=r((e=>{if(4!==e.target.value.length)return;const t=Number.parseInt(e.target.value);if(Number.isNaN(t))return;let n=12*(t-P.getFullYear());const a=new Date(P.getFullYear(),P.getMonth()+n,P.getDate());F&&F.getFullYear()===a.getFullYear()&&F.getMonth()<a.getMonth()?n-=a.getMonth()-F.getMonth():C&&C.getFullYear()===a.getFullYear()&&C.getMonth()>a.getMonth()&&(n+=C.getMonth()-a.getMonth()),U({type:"ADD_OFFSET",addedOffset:n})}),[P,C,F]),oe=r((e=>{if(!q&&!_)return;const t=P.getFullYear()-(q||new Date).getFullYear(),n=Number.parseInt(e.target.value)-(q||new Date).getMonth();U({type:"SET_OFFSET",newOffset:12*t+n})}),[q,_,P]),re=w(H,C,F,O),ce=k(H,E,C,F);return e("div",{ref:A,id:R,className:"jkl-calendar","data-testid":"jkl-calendar",children:t("div",{className:"jkl-calendar__padding",ref:Q,onKeyDown:ee,children:[t("fieldset",{className:"jkl-calendar-navigation",children:[t("div",{children:[e("button",{...W({calendars:V,onClick:ne}),className:"jkl-calendar-navigation__arrow",type:"button",children:e(l,{variant:"medium",bold:!0})}),e("button",{...B({calendars:V,onClick:ne}),className:"jkl-calendar-navigation__arrow",type:"button",children:e(d,{variant:"medium",bold:!0})})]}),t("div",{children:[t("div",{className:"jkl-calendar-navigation-dropdown",children:[e("select",{onChange:oe,className:"jkl-calendar-navigation-dropdown__select","aria-label":Y,value:K.toString(),children:ce.map((({label:t,value:n})=>e("option",{value:n,children:t},n)))}),e(u,{bold:!0,className:"jkl-calendar-navigation-dropdown__chevron"})]}),t("div",{className:"jkl-calendar-navigation-dropdown",children:[e("select",{onChange:ae,className:"jkl-calendar-navigation-dropdown__select","aria-label":x,value:H.toString(),children:re.map((t=>e("option",{value:t,children:t},t)))}),e(u,{bold:!0,className:"jkl-calendar-navigation-dropdown__chevron"})]})]})]}),V.map((n=>t("table",{className:"jkl-calendar-table","data-testid":"jkl-datepicker-calendar",children:[t("caption",{className:"jkl-sr-only",children:[E[n.month],", ",n.year]}),e("thead",{children:e("tr",{children:N.map((t=>e("th",{children:t},`${n.month}${n.year}${t}`)))})}),e("tbody",{"data-testid":"jkl-datepicker-dates",children:n.weeks.map(((t,a)=>e("tr",{children:t.map(((t,o)=>{const r=`${n.month}${n.year}${a}${o}`;if("string"==typeof t)return e("td",{className:"jkl-calendar__date jkl-calendar__date--empty",children:t},r);const{date:c,selectable:i,today:s,prevMonth:l,nextMonth:d}=t;return e("td",{children:e("button",{...z({dateObj:t}),type:"button",className:"jkl-calendar-date-button",tabIndex:te(t)?0:-1,"aria-label":`${c.getDate()}. ${E[c.getMonth()].toLowerCase()}`,"aria-current":s?"date":void 0,"data-adjacent":l||d?"true":void 0,disabled:!i,onKeyDown:Z,children:e("span",{"aria-hidden":"true",children:c.getDate()})})},r)}))},`${n.month}${n.year}${a}`)))})]},`${n.month}${n.year}`)))]})})}));A.displayName="Calendar";export{A as Calendar};
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import{forwardRef as a,useReducer as n,useEffect as r,useCallback as l,useRef as o}from"react";import{flushSync as s}from"react-dom";import{useId as d}from"../../../hooks/useId/useId.js";import{ArrowLeftIcon as c}from"../../icon/icons/ArrowLeftIcon.js";import{ArrowRightIcon as i}from"../../icon/icons/ArrowRightIcon.js";import{ChevronDownIcon as u}from"../../icon/icons/ChevronDownIcon.js";import{calendarReducer as h,calendarInitializer as g}from"./calendarReducer.js";import{useCalendar as m}from"./useCalendar.js";import{getInitialDateShown as f,isBackDisabled as b,subtractMonth as p,isForwardDisabled as v,addMonth as k,getYearSelectOptions as j,getMonthSelectOptions as D,DEFAULT_YEARS_TO_SHOW as w}from"./utils.js";const y=["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],_=["man","tir","ons","tor","fre","lør","søn"],M=a(((a,M)=>{const{date:S,defaultSelected:F,density:A,minDate:N,maxDate:E,days:Y=_,months:x=y,monthLabel:O="Velg måned",yearLabel:C="Velg år",yearsToShow:I=w,onTabOutside:$,...T}=a,R=d("jkl-calendar"),[{offset:L,selectedDate:q,shownDate:K},J]=n(h,f(S,F,N,E),g),P=K.getMonth(),B=K.getFullYear();r((()=>{J({type:"SET_SELECTED_DATE",newDate:f(S,F,N,E)})}),[S,F,N,E]);const U=l((e=>{J({type:"SET_OFFSET",newOffset:e})}),[]),{calendars:V,getBackProps:W,getDateProps:z,getForwardProps:H,handleOffsetChanged:G}=m({date:q,selected:q,minDate:N,maxDate:E,offset:L,onOffsetChanged:U,firstDayOfWeek:1,...T}),Q=o(null),X=l((e=>{if(!Q.current)return;const t=document.activeElement,a=Q.current.querySelectorAll('button.jkl-calendar-date-button:not([data-adjacent="true"]'),n=async e=>{null==t||t.setAttribute("tabindex","-1"),e.setAttribute("tabindex","0"),e.focus()};a.forEach(((r,l)=>{const o=l+e;if(r==t)if(o<=a.length-1&&o>=0)n(a[o]);else if(e<0){if(b({calendars:V,minDate:N})||(s((()=>{G(L-p({calendars:V,offset:1,minDate:N}))})),!Q.current))return;const e=Q.current.querySelectorAll('button.jkl-calendar-date-button:not([data-adjacent="true"]');e[e.length+o]&&(e[0].setAttribute("tabindex","-1"),n(e[e.length+o]))}else{if(v({calendars:V,maxDate:E})||(s((()=>{G(L+k({calendars:V,offset:1,maxDate:E}))})),!Q.current))return;const e=Q.current.querySelectorAll('button.jkl-calendar-date-button:not([data-adjacent="true"]');e[o-a.length]&&(e[0].setAttribute("tabindex","-1"),n(e[o-a.length]))}}))}),[G,Q,L,V,E,N]),Z=l((e=>{switch(e.key){case"ArrowUp":X(-7),e.preventDefault();break;case"ArrowRight":X(1),e.preventDefault();break;case"ArrowDown":X(7),e.preventDefault();break;case"ArrowLeft":X(-1),e.preventDefault()}}),[X]),ee=l((e=>{var t;if("Tab"!==e.key)return;const a=null==(t=Q.current)?void 0:t.querySelectorAll('button:not([disabled]):not([tabindex="-1"]), select');if(!a)return;const n=a[0],r=a[a.length-1];e.shiftKey||document.activeElement!==r?e.shiftKey&&document.activeElement===n&&(r.focus(),e.preventDefault()):(n.focus(),e.preventDefault())}),[]),te=l((e=>{const{date:t,selected:a,selectable:n,prevMonth:r,nextMonth:l}=e;return!!n&&!(!a&&t.toString()!==(null==N?void 0:N.toString())&&(r||l||K.getFullYear()!==t.getFullYear()||q.getMonth()===t.getMonth()||1!==t.getDate()))}),[K,N,q]),ae=l((()=>{N&&K.getFullYear()-N.getFullYear()==0&&K.getMonth()-N.getMonth()==1?document.querySelectorAll(".jkl-calendar-navigation__arrow")[1].focus():E&&E.getFullYear()-K.getFullYear()==0&&E.getMonth()-K.getMonth()==1&&document.querySelectorAll(".jkl-calendar-navigation__arrow")[0].focus()}),[N,E,K]),ne=l((e=>{if(4!==e.target.value.length)return;const t=Number.parseInt(e.target.value);if(Number.isNaN(t))return;let a=12*(t-K.getFullYear());const n=new Date(K.getFullYear(),K.getMonth()+a,K.getDate());E&&E.getFullYear()===n.getFullYear()&&E.getMonth()<n.getMonth()?a-=n.getMonth()-E.getMonth():N&&N.getFullYear()===n.getFullYear()&&N.getMonth()>n.getMonth()&&(a+=N.getMonth()-n.getMonth()),J({type:"ADD_OFFSET",addedOffset:a})}),[K,N,E]),re=l((e=>{if(!q&&!S)return;const t=K.getFullYear()-(q||new Date).getFullYear(),a=Number.parseInt(e.target.value)-(q||new Date).getMonth();J({type:"SET_OFFSET",newOffset:12*t+a})}),[q,S,K]),le=j(B,N,E,I),oe=D(B,x,N,E);return e("div",{ref:M,id:R,className:"jkl-calendar","data-testid":"jkl-calendar",children:t("div",{className:"jkl-calendar__padding",ref:Q,onKeyDown:ee,children:[t("fieldset",{className:"jkl-calendar-navigation",children:[t("div",{children:[e("button",{...W({calendars:V,onClick:ae}),className:"jkl-calendar-navigation__arrow",type:"button",children:e(c,{variant:"medium",bold:!0})}),e("button",{...H({calendars:V,onClick:ae}),className:"jkl-calendar-navigation__arrow",type:"button",children:e(i,{variant:"medium",bold:!0})})]}),t("div",{children:[t("div",{className:"jkl-calendar-navigation-dropdown",children:[e("select",{onChange:re,className:"jkl-calendar-navigation-dropdown__select","aria-label":O,value:P.toString(),children:oe.map((({label:t,value:a})=>e("option",{value:a,children:t},a)))}),e(u,{bold:!0,className:"jkl-calendar-navigation-dropdown__chevron"})]}),t("div",{className:"jkl-calendar-navigation-dropdown",children:[e("select",{onChange:ne,className:"jkl-calendar-navigation-dropdown__select","aria-label":C,value:B.toString(),children:le.map((t=>e("option",{value:t,children:t},t)))}),e(u,{bold:!0,className:"jkl-calendar-navigation-dropdown__chevron"})]})]})]}),V.map((a=>t("table",{className:"jkl-calendar-table","data-testid":"jkl-datepicker-calendar",children:[t("caption",{className:"jkl-sr-only",children:[x[a.month],", ",a.year]}),e("thead",{children:e("tr",{children:Y.map((t=>e("th",{children:t},`${a.month}${a.year}${t}`)))})}),e("tbody",{"data-testid":"jkl-datepicker-dates",children:a.weeks.map(((t,n)=>e("tr",{children:t.map(((t,r)=>{const l=`${a.month}${a.year}${n}${r}`;if("string"==typeof t)return e("td",{className:"jkl-calendar__date jkl-calendar__date--empty",children:t},l);const{date:o,selectable:s,today:d,prevMonth:c,nextMonth:i}=t;return e("td",{children:e("button",{...z({dateObj:t}),type:"button",className:"jkl-calendar-date-button",tabIndex:te(t)?0:-1,"aria-label":`${o.getDate()}. ${x[o.getMonth()].toLowerCase()}`,"aria-current":d?"date":void 0,"data-adjacent":c||i?"true":void 0,disabled:!s,onKeyDown:Z,children:e("span",{"aria-hidden":"true",children:o.getDate()})})},l)}))},`${a.month}${a.year}${n}`)))})]},`${a.month}${a.year}`)))]})})}));M.displayName="Calendar";export{M as Calendar};
2
2
  //# sourceMappingURL=Calendar.js.map