@fremtind/jokul 4.4.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/build/build-stats.html +1 -1
  2. package/build/cjs/components/datepicker/DatePicker.cjs +1 -1
  3. package/build/cjs/components/datepicker/DatePicker.cjs.map +1 -1
  4. package/build/cjs/components/expander/ExpandablePanel.cjs +1 -1
  5. package/build/cjs/components/expander/ExpandablePanel.cjs.map +1 -1
  6. package/build/cjs/components/popover/Popover.cjs +1 -1
  7. package/build/cjs/components/popover/Popover.cjs.map +1 -1
  8. package/build/es/components/datepicker/DatePicker.js +1 -1
  9. package/build/es/components/datepicker/DatePicker.js.map +1 -1
  10. package/build/es/components/expander/ExpandablePanel.js +1 -1
  11. package/build/es/components/expander/ExpandablePanel.js.map +1 -1
  12. package/build/es/components/popover/Popover.js +1 -1
  13. package/build/es/components/popover/Popover.js.map +1 -1
  14. package/package.json +1 -1
  15. package/styles/components/button/button.css +4 -0
  16. package/styles/components/button/button.min.css +1 -1
  17. package/styles/components/button/button.scss +11 -11
  18. package/styles/components/card/card.css +1 -1
  19. package/styles/components/card/card.min.css +1 -1
  20. package/styles/components/card/card.scss +1 -1
  21. package/styles/components/checkbox/checkbox.css +28 -1
  22. package/styles/components/checkbox/checkbox.min.css +1 -1
  23. package/styles/components/checkbox/checkbox.scss +10 -1
  24. package/styles/components/checkbox-panel/checkbox-panel.css +31 -1
  25. package/styles/components/checkbox-panel/checkbox-panel.min.css +1 -1
  26. package/styles/components/checkbox-panel/checkbox-panel.scss +4 -0
  27. package/styles/components/combobox/combobox.css +4 -1
  28. package/styles/components/combobox/combobox.min.css +1 -1
  29. package/styles/components/combobox/combobox.scss +4 -1
  30. package/styles/components/countdown/countdown.css +2 -2
  31. package/styles/components/countdown/countdown.min.css +1 -1
  32. package/styles/components/expander/expandable.css +14 -14
  33. package/styles/components/expander/expandable.min.css +1 -1
  34. package/styles/components/expander/expandable.scss +13 -17
  35. package/styles/components/feedback/feedback.css +6 -8
  36. package/styles/components/feedback/feedback.min.css +1 -1
  37. package/styles/components/feedback/feedback.scss +3 -9
  38. package/styles/components/file-input/file-input.css +13 -9
  39. package/styles/components/file-input/file-input.min.css +1 -1
  40. package/styles/components/input-group/input-group.css +2 -2
  41. package/styles/components/input-group/input-group.min.css +1 -1
  42. package/styles/components/link-list/link-list.css +4 -1
  43. package/styles/components/link-list/link-list.min.css +1 -1
  44. package/styles/components/link-list/link-list.scss +4 -1
  45. package/styles/components/loader/loader.css +6 -6
  46. package/styles/components/loader/loader.min.css +1 -1
  47. package/styles/components/loader/skeleton-loader.css +3 -3
  48. package/styles/components/loader/skeleton-loader.min.css +1 -1
  49. package/styles/components/message/message.css +2 -2
  50. package/styles/components/message/message.min.css +1 -1
  51. package/styles/components/popover/popover.css +11 -0
  52. package/styles/components/popover/popover.min.css +1 -1
  53. package/styles/components/popover/popover.scss +14 -0
  54. package/styles/components/progress-bar/progress-bar.css +25 -1
  55. package/styles/components/progress-bar/progress-bar.min.css +1 -1
  56. package/styles/components/progress-bar/progress-bar.scss +5 -0
  57. package/styles/components/radio-button/radio-button.css +29 -1
  58. package/styles/components/radio-button/radio-button.min.css +1 -1
  59. package/styles/components/radio-button/radio-button.scss +11 -1
  60. package/styles/components/radio-panel/radio-panel.css +3 -0
  61. package/styles/components/radio-panel/radio-panel.min.css +1 -1
  62. package/styles/components/radio-panel/radio-panel.scss +4 -0
  63. package/styles/components/segmented-control/segmented-control.css +31 -3
  64. package/styles/components/segmented-control/segmented-control.min.css +1 -1
  65. package/styles/components/system-message/system-message.css +2 -2
  66. package/styles/components/system-message/system-message.min.css +1 -1
  67. package/styles/components/toast/toast.css +4 -4
  68. package/styles/components/toast/toast.min.css +1 -1
  69. package/styles/components/toggle-switch/toggle-switch.css +2 -7
  70. package/styles/components/toggle-switch/toggle-switch.min.css +2 -2
  71. package/styles/components/toggle-switch/toggle-switch.scss +2 -9
  72. package/styles/styles.css +155 -56
  73. package/styles/styles.min.css +2 -2
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("../../../clsx-E3yX_9sL.cjs"),a=require("../../../utils-DxmZDrR9.cjs"),r=require("react"),n=require("react-dom"),l=require("../icon-button/IconButton.cjs"),o=require("../icon/icons/CalendarIcon.cjs"),u=require("../input-group/InputGroup.cjs"),s=require("../popover/Popover.cjs"),i=require("../text-input/BaseTextInput.cjs"),c=require("./internal/Calendar.cjs"),d=require("./utils.cjs"),p=require("./validation.cjs"),v=r.forwardRef((v,b)=>{const{"data-testautoid":f,id:k,className:h="",label:j="Velg dato",labelProps:m,defaultValue:g,defaultShow:D=!1,value:y,disableBeforeDate:C,disableAfterDate:x,yearsToShow:L,name:P,helpLabel:S,errorLabel:q,invalid:w,days:I,months:O,monthLabel:B,yearLabel:T,placeholder:_="dd.mm.åååå",width:E="11.25rem",onChange:N,onBlur:R,onFocus:U,onKeyDown:V,action:F,showCalendarLabel:K="Åpne kalender",hideCalendarLabel:W="Lukk kalender",supportLabelProps:A,tooltip:G,textInputProps:M,description:H,...z}=v;"production"!==process.env.NODE_ENV&&y&&g&&console.warn("DatePicker må enten være controlled eller uncontrolled. Hvis du bruker defaultValue og value sammen vil defaultValue bli ignorert.");const J=d.parseDateString(C),Q=J?a.dayjs(J).startOf("day").toDate():void 0,X=d.parseDateString(x),Y=X?a.dayjs(X).startOf("day").toDate():void 0,[Z,$]=r.useState(a.getInitialDate(y,g,Q,Y)),[ee,te]=r.useState(null),[ae,re]=r.useState(D),ne=r.useRef(null),le=r.useRef(null),oe=r.useRef(null),ue=r.useRef(null),se=r.useCallback(e=>{ue.current=e,b&&("function"==typeof b?b(e):b.current=e)},[b]),ie=r.useCallback(e=>{U&&le.current&&(le.current.contains(e.relatedTarget)||U(e,Z,{error:ee,value:e.target.value}))},[U,Z,ee]),ce=r.useCallback(e=>{R&&R(e,Z,{error:ee,value:e.target.value})},[R,Z,ee]),de=r.useCallback(e=>{"Escape"===e.key&&(re(!1),e.preventDefault(),e.stopPropagation()),F?.onKeyDown&&F.onKeyDown(e)},[F]),pe=r.useCallback(e=>{let t=null,a=null;if(e.target.value){const r=d.parseDateString(e.target.value);r?Q&&!p.isWithinLowerBound(r,Q)?a="OUTSIDE_LOWER_BOUND":Y&&!p.isWithinUpperBound(r,Y)?a="OUTSIDE_UPPER_BOUND":re(!1):a="WRONG_FORMAT",t=r||null}te(a),$(t),N&&N(e,t,{error:a,value:e.target.value})},[N,Q,Y]),ve=r.useCallback(e=>{n.flushSync(()=>{re(!ae)});const t=ne.current,a=t&&t.querySelector('[aria-pressed="true"]');window.requestAnimationFrame(()=>a?.focus()),F?.onClick&&F.onClick(e)},[ae,F]),be=r.useCallback(({date:e})=>{if(re(!1),$(e),ue.current){const t=ue.current;t.value=d.formatInput(e);const a=document.createEvent("HTMLEvents");a.initEvent("input",!0,!1),t.dispatchEvent(a),t.focus(),N&&N(a,e,{error:null,value:t.value})}},[N]),fe=r.useCallback(e=>{e.preventDefault(),re(!1),oe.current?.focus()},[]);return e.jsx(u.InputGroup,{id:k,className:t.clsx("jkl-datepicker",h),...z,ref:le,label:j,labelProps:m,helpLabel:S,errorLabel:q,supportLabelProps:A,tooltip:G,description:H,render:t=>e.jsx(i.BaseTextInput,{"data-focused":ae?"true":void 0,ref:se,"data-testid":"jkl-datepicker__input","data-testautoid":f,className:"jkl-datepicker__input",name:P,defaultValue:g,value:y,type:"text",placeholder:_,width:E,onFocus:ie,onBlur:ce,onChange:pe,actionButton:e.jsxs(s.Popover,{positionReference:ue,open:ae,onOpenChange:()=>re(!ae),offset:8,children:[e.jsx(s.Popover.Trigger,{...F,"data-testid":"jkl-datepicker__trigger",className:"jkl-text-input-action-button",title:ae?W:K,tabIndex:0,onClick:ve,onKeyDown:de,asChild:!0,children:e.jsx(l.IconButton,{children:e.jsx(o.CalendarIcon,{})})}),e.jsx(s.Popover.Content,{initialFocus:-1,padding:24,children:e.jsx(c.Calendar,{ref:ne,date:Z,minDate:Q,maxDate:Y,days:I,months:O,monthLabel:B,yearLabel:T,yearsToShow:L,onDateSelected:be,onTabOutside:fe})})]}),...M,...t,"aria-invalid":w||!!q})})});v.displayName="DatePicker",exports.DatePicker=v;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("../../../clsx-E3yX_9sL.cjs"),r=require("../../../utils-DxmZDrR9.cjs"),a=require("react"),n=require("react-dom"),l=require("../../utilities/formatters/date/formatDate.cjs"),o=require("../icon-button/IconButton.cjs"),u=require("../icon/icons/CalendarIcon.cjs"),s=require("../input-group/InputGroup.cjs"),i=require("../popover/Popover.cjs"),c=require("../text-input/BaseTextInput.cjs"),d=require("./internal/Calendar.cjs"),p=require("./utils.cjs"),v=require("./validation.cjs"),f=a.forwardRef((f,D)=>{const{"data-testautoid":b,id:m,className:g="",label:j="Velg dato",labelProps:k,defaultValue:h,defaultShow:y=!1,value:x,disableBeforeDate:C,disableAfterDate:S,yearsToShow:L,name:P,helpLabel:q,errorLabel:w,invalid:I,days:O,months:T,monthLabel:B,yearLabel:E,placeholder:_="dd.mm.åååå",width:N="11.25rem",onChange:R,onBlur:U,onFocus:V,onKeyDown:F,action:K,showCalendarLabel:M="Åpne kalender",hideCalendarLabel:W="Lukk kalender",supportLabelProps:A,tooltip:G,textInputProps:H,description:$,...z}=f;"production"!==process.env.NODE_ENV&&x&&h&&console.warn("DatePicker må enten være controlled eller uncontrolled. Hvis du bruker defaultValue og value sammen vil defaultValue bli ignorert.");const J=p.parseDateString(C),Q=J?r.dayjs(J).startOf("day").toDate():void 0,X=p.parseDateString(S),Y=X?r.dayjs(X).startOf("day").toDate():void 0,[Z,ee]=a.useState(r.getInitialDate(x,h,Q,Y)),[te,re]=a.useState(null),[ae,ne]=a.useState(y),le=a.useRef(null),oe=a.useRef(null),ue=a.useRef(null),se=a.useRef(null),ie=a.useCallback(e=>{se.current=e,D&&("function"==typeof D?D(e):D.current=e)},[D]),ce=a.useCallback(e=>{V&&oe.current&&(oe.current.contains(e.relatedTarget)||V(e,Z,{error:te,value:e.target.value}))},[V,Z,te]),de=a.useCallback(e=>{U&&U(e,Z,{error:te,value:e.target.value})},[U,Z,te]),pe=a.useCallback(e=>{"Escape"===e.key&&(ne(!1),e.preventDefault(),e.stopPropagation()),K?.onKeyDown&&K.onKeyDown(e)},[K]),ve=a.useCallback(e=>{const t=e.currentTarget.value,r=(e=>{const t=e.replace(/\D/g,""),r=l.formatDateString(t,{partial:!0}),a=e.replace(/\D+$/,""),n=8===t.length?l.formatDateString(t):e,o=p.parseDateString(n)?n:null,u=e!==t&&a===r&&void 0===p.parseDateString(e)&&null===o;return o??(u?t:e)})(t);r!==t&&((e,t)=>{const r=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"value")?.set;r?r.call(e,t):e.value=t})(e.currentTarget,r);const{date:a,error:n}=(({value:e,minDate:t,maxDate:r})=>{if(!e)return{date:null,error:null};const a=p.parseDateString(e);return a?t&&!v.isWithinLowerBound(a,t)?{date:a,error:"OUTSIDE_LOWER_BOUND"}:r&&!v.isWithinUpperBound(a,r)?{date:a,error:"OUTSIDE_UPPER_BOUND"}:{date:a,error:null}:{date:null,error:"WRONG_FORMAT"}})({value:r,minDate:Q,maxDate:Y});a&&!n&&ne(!1),re(n),ee(a),R&&R(e,a,{error:n,value:r})},[R,Q,Y]),fe=a.useCallback(e=>{n.flushSync(()=>{ne(!ae)});const t=le.current,r=t&&t.querySelector('[aria-pressed="true"]');window.requestAnimationFrame(()=>r?.focus()),K?.onClick&&K.onClick(e)},[ae,K]),De=a.useCallback(({date:e})=>{if(ne(!1),ee(e),se.current){const t=se.current;t.value=p.formatInput(e);const r=document.createEvent("HTMLEvents");r.initEvent("input",!0,!1),t.dispatchEvent(r),t.focus(),R&&R(r,e,{error:null,value:t.value})}},[R]),be=a.useCallback(e=>{e.preventDefault(),ne(!1),ue.current?.focus()},[]);return e.jsx(s.InputGroup,{id:m,className:t.clsx("jkl-datepicker",g),...z,ref:oe,label:j,labelProps:k,helpLabel:q,errorLabel:w,supportLabelProps:A,tooltip:G,description:$,render:t=>e.jsx(c.BaseTextInput,{"data-focused":ae?"true":void 0,ref:ie,"data-testid":"jkl-datepicker__input","data-testautoid":b,className:"jkl-datepicker__input",name:P,defaultValue:h,value:x,type:"text",placeholder:_,width:N,onFocus:ce,onBlur:de,onChange:ve,actionButton:e.jsxs(i.Popover,{positionReference:se,open:ae,onOpenChange:()=>ne(!ae),offset:8,children:[e.jsx(i.Popover.Trigger,{...K,"data-testid":"jkl-datepicker__trigger",className:"jkl-text-input-action-button",title:ae?W:M,tabIndex:0,onClick:fe,onKeyDown:pe,asChild:!0,children:e.jsx(o.IconButton,{children:e.jsx(u.CalendarIcon,{})})}),e.jsx(i.Popover.Content,{initialFocus:-1,padding:24,children:e.jsx(d.Calendar,{ref:le,date:Z,minDate:Q,maxDate:Y,days:O,months:T,monthLabel:B,yearLabel:E,yearsToShow:L,onDateSelected:De,onTabOutside:be})})]}),...H,...t,"aria-invalid":I||!!w})})});f.displayName="DatePicker",exports.DatePicker=f;
2
2
  //# sourceMappingURL=DatePicker.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker.cjs","sources":["../../../../src/components/datepicker/DatePicker.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport dayjs from \"dayjs\";\nimport React, {\n type ChangeEvent,\n type FocusEvent,\n type KeyboardEvent,\n type MouseEvent,\n forwardRef,\n useCallback,\n useRef,\n useState,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { CalendarIcon } from \"../icon/icons/CalendarIcon.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 { type DateInfo, getInitialDate } from \"./internal/utils.js\";\nimport type { 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 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 tooltip,\n textInputProps,\n description,\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 ? dayjs(disableBeforeDate).startOf(\"day\").toDate()\n : undefined;\n const disableAfterDate = parseDateString(disableAfter);\n const maxDate = disableAfterDate\n ? dayjs(disableAfterDate).startOf(\"day\").toDate()\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 [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 [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, 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?.focus());\n\n if (action?.onClick) {\n action.onClick(e);\n }\n },\n [showCalendar, action],\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 [onChange],\n );\n\n const handleTabOutsideCalendar = useCallback((e: KeyboardEvent) => {\n e.preventDefault();\n setShowCalendar(false);\n iconButtonRef.current?.focus();\n }, []);\n\n return (\n <InputGroup\n id={id}\n className={clsx(\"jkl-datepicker\", className)}\n {...rest}\n ref={datepickerRef}\n label={label}\n labelProps={labelProps}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n supportLabelProps={supportLabelProps}\n tooltip={tooltip}\n description={description}\n render={(inputProps) => (\n <BaseTextInput\n data-focused={showCalendar ? \"true\" : undefined}\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 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 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 {...textInputProps}\n {...inputProps}\n aria-invalid={invalid || !!errorLabel}\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","days","months","monthLabel","yearLabel","placeholder","width","onChange","onBlur","onFocus","onKeyDown","action","showCalendarLabel","hideCalendarLabel","supportLabelProps","tooltip","textInputProps","description","rest","process","env","NODE_ENV","console","warn","parseDateString","minDate","dayjs","startOf","toDate","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.cjs","sources":["../../../../src/components/datepicker/DatePicker.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport dayjs from \"dayjs\";\nimport React, {\n type ChangeEvent,\n type FocusEvent,\n type KeyboardEvent,\n type MouseEvent,\n forwardRef,\n useCallback,\n useRef,\n useState,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { formatDateString } from \"../../utilities/formatters/date/formatDate.js\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { CalendarIcon } from \"../icon/icons/CalendarIcon.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 { type DateInfo, getInitialDate } from \"./internal/utils.js\";\nimport type { DatePickerProps, DateValidationError } from \"./types.js\";\nimport { formatInput, parseDateString } from \"./utils.js\";\nimport { isWithinLowerBound, isWithinUpperBound } from \"./validation.js\";\n\nconst setInputValue = (input: HTMLInputElement, value: string) => {\n const nativeSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n \"value\",\n )?.set;\n\n if (nativeSetter) {\n nativeSetter.call(input, value);\n } else {\n input.value = value;\n }\n};\n\nconst normalizeInputValue = (rawValue: string) => {\n const digits = rawValue.replace(/\\D/g, \"\");\n const partialCompactDate = formatDateString(digits, {\n partial: true,\n });\n const rawValueWithoutTrailingPunctuation = rawValue.replace(/\\D+$/, \"\");\n const compactDateCandidate =\n digits.length === 8 ? formatDateString(digits) : rawValue;\n const validCompactDate = parseDateString(compactDateCandidate)\n ? compactDateCandidate\n : null;\n const shouldRemoveFormatting =\n rawValue !== digits &&\n rawValueWithoutTrailingPunctuation === partialCompactDate &&\n parseDateString(rawValue) === undefined &&\n validCompactDate === null;\n\n return validCompactDate ?? (shouldRemoveFormatting ? digits : rawValue);\n};\n\nconst getInputValidationState = ({\n value,\n minDate,\n maxDate,\n}: {\n value: string;\n minDate?: Date;\n maxDate?: Date;\n}): { date: Date | null; error: DateValidationError | null } => {\n if (!value) {\n return { date: null, error: null };\n }\n\n const parsedDate = parseDateString(value);\n\n if (!parsedDate) {\n return { date: null, error: \"WRONG_FORMAT\" };\n }\n\n if (minDate && !isWithinLowerBound(parsedDate, minDate)) {\n return { date: parsedDate, error: \"OUTSIDE_LOWER_BOUND\" };\n }\n\n if (maxDate && !isWithinUpperBound(parsedDate, maxDate)) {\n return { date: parsedDate, error: \"OUTSIDE_UPPER_BOUND\" };\n }\n\n return { date: parsedDate, error: null };\n};\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 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 tooltip,\n textInputProps,\n description,\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 ? dayjs(disableBeforeDate).startOf(\"day\").toDate()\n : undefined;\n const disableAfterDate = parseDateString(disableAfter);\n const maxDate = disableAfterDate\n ? dayjs(disableAfterDate).startOf(\"day\").toDate()\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 [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 [action],\n );\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n const rawValue = e.currentTarget.value;\n const formattedValue = normalizeInputValue(rawValue);\n\n if (formattedValue !== rawValue) {\n setInputValue(e.currentTarget, formattedValue);\n }\n\n const { date: nextDate, error: nextError } =\n getInputValidationState({\n value: formattedValue,\n minDate,\n maxDate,\n });\n\n if (nextDate && !nextError) {\n setShowCalendar(false);\n }\n\n setError(nextError);\n setDate(nextDate);\n\n if (onChange) {\n onChange(e, nextDate, {\n error: nextError,\n value: formattedValue,\n });\n }\n },\n [onChange, 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?.focus());\n\n if (action?.onClick) {\n action.onClick(e);\n }\n },\n [showCalendar, action],\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 [onChange],\n );\n\n const handleTabOutsideCalendar = useCallback((e: KeyboardEvent) => {\n e.preventDefault();\n setShowCalendar(false);\n iconButtonRef.current?.focus();\n }, []);\n\n return (\n <InputGroup\n id={id}\n className={clsx(\"jkl-datepicker\", className)}\n {...rest}\n ref={datepickerRef}\n label={label}\n labelProps={labelProps}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n supportLabelProps={supportLabelProps}\n tooltip={tooltip}\n description={description}\n render={(inputProps) => (\n <BaseTextInput\n data-focused={showCalendar ? \"true\" : undefined}\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 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 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 {...textInputProps}\n {...inputProps}\n aria-invalid={invalid || !!errorLabel}\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","days","months","monthLabel","yearLabel","placeholder","width","onChange","onBlur","onFocus","onKeyDown","action","showCalendarLabel","hideCalendarLabel","supportLabelProps","tooltip","textInputProps","description","rest","process","env","NODE_ENV","console","warn","parseDateString","minDate","dayjs","startOf","toDate","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","rawValue","currentTarget","formattedValue","digits","replace","partialCompactDate","formatDateString","partial","rawValueWithoutTrailingPunctuation","compactDateCandidate","length","validCompactDate","shouldRemoveFormatting","normalizeInputValue","input","nativeSetter","Object","getOwnPropertyDescriptor","HTMLInputElement","prototype","set","call","setInputValue","nextDate","nextError","parsedDate","isWithinLowerBound","isWithinUpperBound","getInputValidationState","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
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("../../../clsx-E3yX_9sL.cjs"),n=require("react"),a=require("./ExpandablePanelContent.cjs"),r=require("./context.cjs"),s=require("./Expander.cjs"),i=Object.assign(n.forwardRef(function(a,s){const{children:i,as:l="details",variant:o="fill",open:d,defaultOpen:c,onOpenChange:u,className:p,...x}=a,[j,f]=n.useState(c||!1),[b,g]=n.useState(!1),[v,E]=n.useState(0),h=n.useRef();n.useImperativeHandle(s,()=>h.current,[]);const m=l,S=typeof d<"u",q=S?d:j;return n.useEffect(()=>{const e=e=>{f("open"===e.newState)},t=h.current;return t?.addEventListener("toggle",e),()=>t?.removeEventListener("toggle",e)},[]),e.jsxs("div",{className:"jkl-expandable__wrapper",children:[e.jsx("div",{ref:e=>e?.setAttribute("inert","true"),className:"jkl-expandable__focus-container",style:{height:v}}),e.jsx(m,{ref:h,"data-testid":"jkl-expand-section",className:t.clsx("jkl-expandable",`jkl-expandable--${o}`,p),open:"details"===l?q||b:void 0,"data-visible-content":q||b,...x,children:e.jsx(r.ExpanderContext.Provider,{value:{open:q,onToggle:()=>{S||f(e=>(u?.(!e),!e))},onTransitionEnd:g,onTransitionStart:e=>{e&&g(!0)},setExpanderHeight:E},children:i})})]})}),{Content:a.ExpandablePanelContent,Header:s.Expander});exports.ExpandablePanel=i;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("../../../clsx-E3yX_9sL.cjs"),n=require("react"),a=require("./ExpandablePanelContent.cjs"),r=require("./Expander.cjs"),s=require("./context.cjs"),i=Object.assign(n.forwardRef(function(a,r){const{children:i,as:l="details",variant:o="fill",open:d,defaultOpen:c,onOpenChange:u,className:p,...x}=a,[j,f]=n.useState(c||!1),[b,g]=n.useState(!1),[v,E]=n.useState(0),h=n.useRef();n.useImperativeHandle(r,()=>h.current,[]);const m=l,S=typeof d<"u",q=S?d:j;return n.useEffect(()=>{const e=e=>{f("open"===e.newState)},t=h.current;return t?.addEventListener("toggle",e),()=>t?.removeEventListener("toggle",e)},[]),e.jsxs("div",{className:"jkl-expandable__wrapper",children:[e.jsx("div",{ref:e=>e?.setAttribute("inert","true"),className:"jkl-expandable__focus-container",style:{height:v}}),e.jsx(m,{ref:h,"data-testid":"jkl-expand-section",className:t.clsx("jkl-expandable",`jkl-expandable--${o}`,p),open:"details"===l?q||b:void 0,"data-visible-content":q||b,...x,children:e.jsx(s.ExpanderContext.Provider,{value:{open:q,onToggle:()=>{S?u?.(!q):f(e=>(u?.(!e),!e))},onTransitionEnd:g,onTransitionStart:e=>{e&&g(!0)},setExpanderHeight:E},children:i})})]})}),{Content:a.ExpandablePanelContent,Header:r.Expander});exports.ExpandablePanel=i;
2
2
  //# sourceMappingURL=ExpandablePanel.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpandablePanel.cjs","sources":["../../../../src/components/expander/ExpandablePanel.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport type { PolymorphicRef } from \"../../utilities/polymorphism/polymorphism.js\";\nimport { ExpandablePanelContent } from \"./ExpandablePanelContent.js\";\nimport { ExpanderContext } from \"./context.js\";\nimport type {\n ExpandablePanelComponent,\n ExpandablePanelProps,\n} from \"./types.js\";\nimport { Expander } from \"./Expander.jsx\";\n\nexport const ExpandablePanel = Object.assign(\n React.forwardRef(function ExpandablePanel<\n ElementType extends React.ElementType = \"details\",\n >(\n props: ExpandablePanelProps<ElementType>,\n ref?: PolymorphicRef<ElementType>,\n ) {\n const {\n children,\n as = \"details\",\n variant = \"fill\",\n open: controlledOpen,\n defaultOpen,\n onOpenChange,\n className,\n ...rest\n } = props;\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(\n defaultOpen || false,\n );\n const [contentIsVisible, setContentIsVisible] = useState(false);\n const [expanderHeight, setExpanderHeight] = useState(0);\n\n const internalRef = useRef<HTMLDetailsElement>();\n useImperativeHandle(ref, () => internalRef.current, []);\n\n const El = as;\n const isControlled = typeof controlledOpen !== \"undefined\";\n const isOpen = isControlled ? controlledOpen : uncontrolledOpen;\n\n const setVisibleIfOpening = (isOpening: boolean) => {\n if (isOpening) {\n setContentIsVisible(true);\n }\n };\n\n const syncUncontrolledState = () => {\n if (isControlled) {\n return;\n }\n setUncontrolledOpen((previousValue) => {\n onOpenChange?.(!previousValue);\n return !previousValue;\n });\n };\n\n useEffect(() => {\n const callback = (e: ToggleEvent & { newState: string }) => {\n setUncontrolledOpen(e.newState === \"open\");\n };\n\n const element = internalRef.current;\n\n element?.addEventListener(\"toggle\", callback as EventListener);\n\n return () =>\n element?.removeEventListener(\n \"toggle\",\n callback as EventListener,\n );\n }, []);\n\n return (\n <div className=\"jkl-expandable__wrapper\">\n <div\n /*\n Setter `inert` manuelt for å støtte både React 18 og 19.\n\n Dette unngår typefeil i React 18 og advarsler i React 19.\n Se: https://github.com/WICG/inert/issues/58\n */\n ref={(node) => node?.setAttribute(\"inert\", \"true\")}\n className=\"jkl-expandable__focus-container\"\n style={{ height: expanderHeight }}\n />\n <El\n ref={internalRef}\n data-testid={\"jkl-expand-section\"}\n className={clsx(\n \"jkl-expandable\",\n `jkl-expandable--${variant}`,\n className,\n )}\n open={\n /* for the animation to work in Safari we must ensure that\n * the element is open *before* the transition starts */\n as === \"details\"\n ? isOpen || contentIsVisible\n : undefined\n }\n /* this attribute is used for styling purposes */\n data-visible-content={isOpen || contentIsVisible}\n {...rest}\n >\n <ExpanderContext.Provider\n value={{\n open: isOpen,\n onToggle: syncUncontrolledState,\n onTransitionEnd: setContentIsVisible,\n onTransitionStart: setVisibleIfOpening,\n setExpanderHeight,\n }}\n >\n {children}\n </ExpanderContext.Provider>\n </El>\n </div>\n );\n }),\n { Content: ExpandablePanelContent, Header: Expander },\n) as ExpandablePanelComponent;\n"],"names":["ExpandablePanel","Object","assign","React","forwardRef","props","ref","children","as","variant","open","controlledOpen","defaultOpen","onOpenChange","className","rest","uncontrolledOpen","setUncontrolledOpen","useState","contentIsVisible","setContentIsVisible","expanderHeight","setExpanderHeight","internalRef","useRef","useImperativeHandle","current","El","isControlled","isOpen","useEffect","callback","e","newState","element","addEventListener","removeEventListener","jsxs","jsx","node","setAttribute","style","height","clsx","ExpanderContext","Provider","value","onToggle","previousValue","onTransitionEnd","onTransitionStart","isOpening","Content","ExpandablePanelContent","Header","Expander"],"mappings":"iRAWaA,EAAkBC,OAAOC,OAClCC,EAAMC,WAAW,SAGbC,EACAC,GAEA,MACIC,SAAAA,EACAC,GAAAA,EAAK,UACLC,QAAAA,EAAU,OACVC,KAAMC,EACNC,YAAAA,EACAC,aAAAA,EACAC,UAAAA,KACGC,GACHV,GAEGW,EAAkBC,GAAuBC,EAAAA,SAC5CN,IAAe,IAEZO,EAAkBC,GAAuBF,EAAAA,UAAS,IAClDG,EAAgBC,GAAqBJ,EAAAA,SAAS,GAE/CK,EAAcC,EAAAA,SACpBC,EAAAA,oBAAoBnB,EAAK,IAAMiB,EAAYG,QAAS,IAEpD,MAAMC,EAAKnB,EACLoB,SAAsBjB,EAAmB,IACzCkB,EAASD,EAAejB,EAAiBK,EAkB/Cc,OAAAA,EAAAA,UAAU,KACN,MAAMC,EAAYC,IACdf,EAAmC,SAAfe,EAAEC,WAGpBC,EAAUX,EAAYG,QAE5B,OAAAQ,GAASC,iBAAiB,SAAUJ,GAE7B,IACHG,GAASE,oBACL,SACAL,IAET,IAGCM,EAAAA,KAAC,MAAA,CAAIvB,UAAU,0BACXP,SAAA,CAAA+B,EAAAA,IAAC,MAAA,CAOGhC,IAAMiC,GAASA,GAAMC,aAAa,QAAS,QAC3C1B,UAAU,kCACV2B,MAAO,CAAEC,OAAQrB,KAErBiB,EAAAA,IAACX,EAAA,CACGrB,IAAKiB,EACL,cAAa,qBACbT,UAAW6B,EAAAA,KACP,iBACA,mBAAmBlC,IACnBK,GAEJJ,KAGW,YAAPF,EACMqB,GAAUV,OACV,EAGV,uBAAsBU,GAAUV,KAC5BJ,EAEJR,SAAA+B,EAAAA,IAACM,EAAAA,gBAAgBC,SAAhB,CACGC,MAAO,CACHpC,KAAMmB,EACNkB,SA7DU,KACtBnB,GAGJX,EAAqB+B,IACjBnC,KAAgBmC,IACRA,KAwDIC,gBAAiB7B,EACjB8B,kBArESC,IACrBA,GACA/B,GAAoB,IAoERE,kBAAAA,GAGHf,SAAAA,QAKrB,GACA,CAAE6C,QAASC,yBAAwBC,OAAQC,EAAAA"}
1
+ {"version":3,"file":"ExpandablePanel.cjs","sources":["../../../../src/components/expander/ExpandablePanel.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport type { PolymorphicRef } from \"../../utilities/polymorphism/polymorphism.js\";\nimport { ExpandablePanelContent } from \"./ExpandablePanelContent.js\";\nimport { Expander } from \"./Expander.jsx\";\nimport { ExpanderContext } from \"./context.js\";\nimport type {\n ExpandablePanelComponent,\n ExpandablePanelProps,\n} from \"./types.js\";\n\nexport const ExpandablePanel = Object.assign(\n React.forwardRef(function ExpandablePanel<\n ElementType extends React.ElementType = \"details\",\n >(\n props: ExpandablePanelProps<ElementType>,\n ref?: PolymorphicRef<ElementType>,\n ) {\n const {\n children,\n as = \"details\",\n variant = \"fill\",\n open: controlledOpen,\n defaultOpen,\n onOpenChange,\n className,\n ...rest\n } = props;\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(\n defaultOpen || false,\n );\n const [contentIsVisible, setContentIsVisible] = useState(false);\n const [expanderHeight, setExpanderHeight] = useState(0);\n\n const internalRef = useRef<HTMLDetailsElement>();\n useImperativeHandle(ref, () => internalRef.current, []);\n\n const El = as;\n const isControlled = typeof controlledOpen !== \"undefined\";\n const isOpen = isControlled ? controlledOpen : uncontrolledOpen;\n\n const setVisibleIfOpening = (isOpening: boolean) => {\n if (isOpening) {\n setContentIsVisible(true);\n }\n };\n\n const syncUncontrolledState = () => {\n if (isControlled) {\n onOpenChange?.(!isOpen);\n return;\n }\n setUncontrolledOpen((previousValue) => {\n onOpenChange?.(!previousValue);\n return !previousValue;\n });\n };\n\n useEffect(() => {\n const callback = (e: ToggleEvent & { newState: string }) => {\n setUncontrolledOpen(e.newState === \"open\");\n };\n\n const element = internalRef.current;\n\n element?.addEventListener(\"toggle\", callback as EventListener);\n\n return () =>\n element?.removeEventListener(\n \"toggle\",\n callback as EventListener,\n );\n }, []);\n\n return (\n <div className=\"jkl-expandable__wrapper\">\n <div\n /*\n Setter `inert` manuelt for å støtte både React 18 og 19.\n\n Dette unngår typefeil i React 18 og advarsler i React 19.\n Se: https://github.com/WICG/inert/issues/58\n */\n ref={(node) => node?.setAttribute(\"inert\", \"true\")}\n className=\"jkl-expandable__focus-container\"\n style={{ height: expanderHeight }}\n />\n <El\n ref={internalRef}\n data-testid={\"jkl-expand-section\"}\n className={clsx(\n \"jkl-expandable\",\n `jkl-expandable--${variant}`,\n className,\n )}\n open={\n /* for the animation to work in Safari we must ensure that\n * the element is open *before* the transition starts */\n as === \"details\"\n ? isOpen || contentIsVisible\n : undefined\n }\n /* this attribute is used for styling purposes */\n data-visible-content={isOpen || contentIsVisible}\n {...rest}\n >\n <ExpanderContext.Provider\n value={{\n open: isOpen,\n onToggle: syncUncontrolledState,\n onTransitionEnd: setContentIsVisible,\n onTransitionStart: setVisibleIfOpening,\n setExpanderHeight,\n }}\n >\n {children}\n </ExpanderContext.Provider>\n </El>\n </div>\n );\n }),\n { Content: ExpandablePanelContent, Header: Expander },\n) as ExpandablePanelComponent;\n"],"names":["ExpandablePanel","Object","assign","React","forwardRef","props","ref","children","as","variant","open","controlledOpen","defaultOpen","onOpenChange","className","rest","uncontrolledOpen","setUncontrolledOpen","useState","contentIsVisible","setContentIsVisible","expanderHeight","setExpanderHeight","internalRef","useRef","useImperativeHandle","current","El","isControlled","isOpen","useEffect","callback","e","newState","element","addEventListener","removeEventListener","jsxs","jsx","node","setAttribute","style","height","clsx","ExpanderContext","Provider","value","onToggle","previousValue","onTransitionEnd","onTransitionStart","isOpening","Content","ExpandablePanelContent","Header","Expander"],"mappings":"iRAWaA,EAAkBC,OAAOC,OAClCC,EAAMC,WAAW,SAGbC,EACAC,GAEA,MACIC,SAAAA,EACAC,GAAAA,EAAK,UACLC,QAAAA,EAAU,OACVC,KAAMC,EACNC,YAAAA,EACAC,aAAAA,EACAC,UAAAA,KACGC,GACHV,GAEGW,EAAkBC,GAAuBC,EAAAA,SAC5CN,IAAe,IAEZO,EAAkBC,GAAuBF,EAAAA,UAAS,IAClDG,EAAgBC,GAAqBJ,EAAAA,SAAS,GAE/CK,EAAcC,EAAAA,SACpBC,EAAAA,oBAAoBnB,EAAK,IAAMiB,EAAYG,QAAS,IAEpD,MAAMC,EAAKnB,EACLoB,SAAsBjB,EAAmB,IACzCkB,EAASD,EAAejB,EAAiBK,EAmB/Cc,OAAAA,EAAAA,UAAU,KACN,MAAMC,EAAYC,IACdf,EAAmC,SAAfe,EAAEC,WAGpBC,EAAUX,EAAYG,QAE5B,OAAAQ,GAASC,iBAAiB,SAAUJ,GAE7B,IACHG,GAASE,oBACL,SACAL,IAET,IAGCM,EAAAA,KAAC,MAAA,CAAIvB,UAAU,0BACXP,SAAA,CAAA+B,EAAAA,IAAC,MAAA,CAOGhC,IAAMiC,GAASA,GAAMC,aAAa,QAAS,QAC3C1B,UAAU,kCACV2B,MAAO,CAAEC,OAAQrB,KAErBiB,EAAAA,IAACX,EAAA,CACGrB,IAAKiB,EACL,cAAa,qBACbT,UAAW6B,EAAAA,KACP,iBACA,mBAAmBlC,IACnBK,GAEJJ,KAGW,YAAPF,EACMqB,GAAUV,OACV,EAGV,uBAAsBU,GAAUV,KAC5BJ,EAEJR,SAAA+B,EAAAA,IAACM,EAAAA,gBAAgBC,SAAhB,CACGC,MAAO,CACHpC,KAAMmB,EACNkB,SA9DU,KACtBnB,EACAf,KAAgBgB,GAGpBZ,EAAqB+B,IACjBnC,KAAgBmC,IACRA,KAwDIC,gBAAiB7B,EACjB8B,kBAtESC,IACrBA,GACA/B,GAAoB,IAqERE,kBAAAA,GAGHf,SAAAA,QAKrB,GACA,CAAE6C,QAASC,yBAAwBC,OAAQC,EAAAA"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("react/jsx-runtime"),t=require("@floating-ui/react"),n=require("../../../clsx-E3yX_9sL.cjs"),o=require("react"),r=require("../../utilities/getThemeAndSize.cjs");const s=function(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const n in e)if("default"!==n){const o=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,o.get?o:{enumerable:!0,get:()=>e[n]})}return t.default=e,Object.freeze(t)}(o),i=s.createContext(null),l=()=>{const e=s.useContext(i);if(null==e)throw new Error("Popover komponenter må brukes innenfor en <Popover /> komponent");return e},a=({children:n,...o})=>{const r=(({open:e,onOpenChange:n,placement:o="bottom-start",strategy:r="absolute",modal:i=!0,offset:l=4,positionReference:a,hoverOptions:c,focusOptions:u,clickOptions:d,roleOptions:f,dismissOptions:p})=>{const[m,g]=s.useState(e),h=e??m,x=n??g,b=t.useFloating({open:h,onOpenChange:x,placement:o,strategy:r,middleware:[t.offset(l),t.flip({padding:5,fallbackPlacements:["bottom","top"]}),t.shift({padding:12})],whileElementsMounted:t.autoUpdate}),j=b.context,v=t.useClick(j,{enabled:!1,...d}),O=t.useHover(j,{enabled:!1,...c}),P=t.useFocus(j,{enabled:!1,...u}),R=t.useDismiss(j,p),y=t.useRole(j,f),F=t.useInteractions([v,R,P,O,y]);return s.useLayoutEffect(()=>{a&&b.refs.setPositionReference(a?.current)},[a,b.refs]),s.useMemo(()=>({open:h,onOpenChange:x,modal:i,...F,...b}),[h,x,i,F,b])})({...o});return e.jsx(i.Provider,{value:r,children:n})},c=s.forwardRef(function({children:n,asChild:o=!1,...r},i){const{refs:a,getReferenceProps:c,open:u,onOpenChange:d}=l(),f=n.ref,p=t.useMergeRefs([a.setReference,i,f]);return o&&s.isValidElement(n)?s.cloneElement(n,c({ref:p,...r,...n.props})):e.jsx("button",{ref:p,onClick:()=>d?.(!u),"aria-expanded":u,...c(r),children:n})}),u=s.forwardRef(function({style:o,className:i,padding:a=0,initialFocus:c=0,returnFocus:u=!0,...d},f){const{context:p,modal:m,refs:g,open:h,floatingStyles:x,getFloatingProps:b}=l(),j=t.useMergeRefs([g.setFloating,f]),v=g.reference.current,{theme:O,size:P}=(y=v)&&"contextElement"in y?r.getThemeAndSize(v.contextElement):r.getThemeAndSize(v),R=s.useRef(null);var y;return s.useEffect(()=>{R.current=p.elements.domReference?.closest("[data-portal]")||document.body},[p.elements.domReference]),h?e.jsx(t.FloatingPortal,{root:R.current,children:e.jsx(t.FloatingFocusManager,{context:p,modal:m,initialFocus:c,returnFocus:u,children:e.jsx("div",{"data-theme":O,"data-size":P,className:n.clsx("jkl jkl-popover",i),ref:j,style:{...o,...x,"--popover-padding":`var(--jkl-spacing-${a})`},...b(d),children:d.children})})}):null});a.Trigger=c,a.Content=u,exports.Popover=a,exports.default=a;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("react/jsx-runtime"),t=require("@floating-ui/react"),n=require("../../../clsx-E3yX_9sL.cjs"),o=require("react"),r=require("../../utilities/getThemeAndSize.cjs");const s=function(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const n in e)if("default"!==n){const o=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,o.get?o:{enumerable:!0,get:()=>e[n]})}return t.default=e,Object.freeze(t)}(o),l=s.createContext(null),i=()=>{const e=s.useContext(l);if(null==e)throw new Error("Popover komponenter må brukes innenfor en <Popover /> komponent");return e},a=({children:n,...o})=>{const r=(({open:e,onOpenChange:n,placement:o="bottom-start",strategy:r="absolute",modal:l=!0,offset:i=4,positionReference:a,hoverOptions:c,focusOptions:u,clickOptions:d,roleOptions:f,dismissOptions:p})=>{const[m,g]=s.useState(e),h=e??m,x=n??g,b=t.useFloating({open:h,onOpenChange:x,placement:o,strategy:r,middleware:[t.offset(i),t.flip({padding:5,fallbackPlacements:["bottom","top"]}),t.shift({padding:12})],whileElementsMounted:t.autoUpdate}),j=b.context,v=t.useClick(j,{enabled:!1,...d}),O=t.useHover(j,{enabled:!1,...c}),P=t.useFocus(j,{enabled:!1,...u}),R=t.useDismiss(j,p),k=t.useRole(j,f),y=t.useInteractions([v,R,P,O,k]);return s.useLayoutEffect(()=>{a&&b.refs.setPositionReference(a?.current)},[a,b.refs]),s.useMemo(()=>({open:h,onOpenChange:x,modal:l,...y,...b}),[h,x,l,y,b])})({...o});return e.jsx(l.Provider,{value:r,children:n})},c=s.forwardRef(function({children:o,asChild:r=!1,...l},a){const{refs:c,getReferenceProps:u,open:d,onOpenChange:f}=i(),p=o.ref,m=t.useMergeRefs([c.setReference,a,p]);return r&&s.isValidElement(o)?s.cloneElement(o,u({ref:m,...l,...o.props})):e.jsx("button",{ref:m,onClick:()=>f?.(!d),"aria-expanded":d,...u({...l,className:n.clsx("jkl-popover-trigger",l.className)}),children:o})}),u=s.forwardRef(function({style:o,className:l,padding:a=0,initialFocus:c=0,returnFocus:u=!0,...d},f){const{context:p,modal:m,refs:g,open:h,floatingStyles:x,getFloatingProps:b}=i(),j=t.useMergeRefs([g.setFloating,f]),v=g.reference.current,{theme:O,size:P}=(k=v)&&"contextElement"in k?r.getThemeAndSize(v.contextElement):r.getThemeAndSize(v),R=s.useRef(null);var k;return s.useEffect(()=>{R.current=p.elements.domReference?.closest("[data-portal]")||document.body},[p.elements.domReference]),h?e.jsx(t.FloatingPortal,{root:R.current,children:e.jsx(t.FloatingFocusManager,{context:p,modal:m,initialFocus:c,returnFocus:u,children:e.jsx("div",{"data-theme":O,"data-size":P,className:n.clsx("jkl jkl-popover",l),ref:j,style:{...o,...x,"--popover-padding":`var(--jkl-spacing-${a})`},...b(d),children:d.children})})}):null});a.Trigger=c,a.Content=u,exports.Popover=a,exports.default=a;
2
2
  //# sourceMappingURL=Popover.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Popover.cjs","sources":["../../../../src/components/popover/Popover.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n FloatingPortal,\n type ReferenceElement,\n type VirtualElement,\n autoUpdate,\n flip,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n useMergeRefs,\n useRole,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport * as React from \"react\";\nimport { getThemeAndSize } from \"../../utilities/getThemeAndSize.js\";\nimport type { PopoverOptions } from \"./types.js\";\n\nconst usePopover = ({\n open: _open,\n onOpenChange: _onOpenChange,\n placement = \"bottom-start\",\n strategy = \"absolute\",\n modal = true,\n offset: _offset = 4,\n positionReference,\n hoverOptions,\n focusOptions,\n clickOptions,\n roleOptions,\n dismissOptions,\n}: PopoverOptions) => {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(_open);\n\n const open = _open ?? uncontrolledOpen;\n const onOpenChange = _onOpenChange ?? setUncontrolledOpen;\n\n const data = useFloating({\n open,\n onOpenChange,\n placement,\n strategy,\n middleware: [\n offset(_offset),\n flip({ padding: 5, fallbackPlacements: [\"bottom\", \"top\"] }),\n shift({ padding: 12 }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const context = data.context;\n\n const click = useClick(context, {\n enabled: false,\n ...clickOptions,\n });\n const hover = useHover(context, { enabled: false, ...hoverOptions });\n const focus = useFocus(context, { enabled: false, ...focusOptions });\n const dismiss = useDismiss(context, dismissOptions);\n const role = useRole(context, roleOptions);\n\n const interactions = useInteractions([click, dismiss, focus, hover, role]);\n\n React.useLayoutEffect(() => {\n if (positionReference) {\n data.refs.setPositionReference(positionReference?.current);\n }\n }, [positionReference, data.refs]);\n\n return React.useMemo(\n () => ({\n open,\n onOpenChange,\n modal,\n ...interactions,\n ...data,\n }),\n [open, onOpenChange, modal, interactions, data],\n );\n};\n\ntype PopoverContextType = ReturnType<typeof usePopover> | null;\n\nconst PopoverContext = React.createContext<PopoverContextType>(null);\n\nconst usePopoverContext = () => {\n const context = React.useContext(PopoverContext);\n\n if (context == null) {\n throw new Error(\n \"Popover komponenter må brukes innenfor en <Popover /> komponent\",\n );\n }\n\n return context;\n};\n\nexport const Popover = ({\n children,\n ...restOptions\n}: {\n children: React.ReactNode;\n} & PopoverOptions) => {\n const popover = usePopover({ ...restOptions });\n return (\n <PopoverContext.Provider value={popover}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\ninterface PopoverTriggerProps {\n children: React.ReactNode;\n /**\n * Rendrer komponenten som child-elementet sitt, og slår sammen egenskaper og props.\n *\n * Default er `false`.\n *\n * @example\n * ```tsx\n * <Component asChild foo=\"bar\">\n * <Child baz=\"qux\" />\n * </Component>\n *\n * // Rendrer følgende:\n * <Child foo=\"bar\" baz=\"qux\" />\n * ```\n */\n asChild?: boolean;\n}\n\nconst PopoverTrigger = React.forwardRef<\n HTMLElement,\n React.HTMLProps<HTMLElement> & PopoverTriggerProps\n>(function PopoverTrigger({ children, asChild = false, ...props }, propRef) {\n const { refs, getReferenceProps, open, onOpenChange } = usePopoverContext();\n const childrenRef = (children as any).ref;\n const ref = useMergeRefs([refs.setReference, propRef, childrenRef]);\n\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(\n children,\n getReferenceProps({\n ref,\n ...props,\n ...children.props,\n }),\n );\n }\n\n return (\n <button\n ref={ref}\n onClick={() => onOpenChange?.(!open)}\n aria-expanded={open}\n {...getReferenceProps(props)}\n >\n {children}\n </button>\n );\n});\n\ninterface PopoverContentProps {\n /**\n * Padding rundt innholdet i popoveren.\n *\n * Default er `0`.\n */\n padding?: 0 | 8 | 16 | 24;\n /**\n *\n * Angir hvilket element som skal motta fokus ved åpning.\n * Kan være en tabbar index eller en referanse til et element.\"\n *\n * Default er `0`, som betyr at det første fokuserbare elementet i popoveren får fokus.\n * @see https://floating-ui.com/docs/FloatingFocusManager#initialfocus\n */\n initialFocus?: number | React.RefObject<HTMLElement>;\n /**\n * Angir om fokus skal returneres til triggeren når popoveren lukkes.\n *\n * Default er `true`.\n * @see https://floating-ui.com/docs/FloatingFocusManager#returnfocus\n */\n returnFocus?: boolean;\n}\n\n// Er popover-elementet posisjonert i forhold til et annet element enn triggeren?\nconst isCustomPositioned = (\n referenceElement: ReferenceElement,\n): referenceElement is VirtualElement => {\n if (!referenceElement) return false;\n\n return \"contextElement\" in referenceElement;\n};\n\nconst PopoverContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLProps<HTMLDivElement> & PopoverContentProps\n>(function PopoverContent(\n {\n style,\n className,\n padding = 0,\n initialFocus = 0,\n returnFocus = true,\n ...props\n },\n propRef,\n) {\n const { context, modal, refs, open, floatingStyles, getFloatingProps } =\n usePopoverContext();\n const ref = useMergeRefs([refs.setFloating, propRef]);\n\n const referenceElement = refs.reference.current as ReferenceElement;\n\n const { theme, size } = isCustomPositioned(referenceElement)\n ? getThemeAndSize(referenceElement.contextElement)\n : getThemeAndSize(referenceElement);\n\n const floatingPortalRef = React.useRef<HTMLElement | null>(null);\n\n // TODO: Løser et problem hvor nestede portaler ikke \"fester\" seg til det nærmeste portal-elementet. Fjernes når alle komponenter som rendres i en portal tar i bruk popover komponenten da den håndterer dette internt. Issue: https://github.com/fremtind/jokul/issues/4356\n React.useEffect(() => {\n floatingPortalRef.current =\n context.elements.domReference?.closest<HTMLElement>(\n \"[data-portal]\",\n ) || document.body;\n }, [context.elements.domReference]);\n\n if (!open) return null;\n\n return (\n <FloatingPortal root={floatingPortalRef.current}>\n <FloatingFocusManager\n context={context}\n modal={modal}\n initialFocus={initialFocus}\n returnFocus={returnFocus}\n >\n <div\n data-theme={theme}\n data-size={size}\n className={clsx(\"jkl jkl-popover\", className)}\n ref={ref}\n style={\n {\n ...style,\n ...floatingStyles,\n \"--popover-padding\": `var(--jkl-spacing-${padding})`,\n } as React.CSSProperties\n }\n {...getFloatingProps(props)}\n >\n {props.children}\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n );\n});\n\nPopover.Trigger = PopoverTrigger;\nPopover.Content = PopoverContent;\n\nexport default Popover;\n"],"names":["PopoverContext","React","createContext","usePopoverContext","context","useContext","Error","Popover","children","restOptions","popover","open","_open","onOpenChange","_onOpenChange","placement","strategy","modal","offset","_offset","positionReference","hoverOptions","focusOptions","clickOptions","roleOptions","dismissOptions","uncontrolledOpen","setUncontrolledOpen","useState","data","useFloating","middleware","flip","padding","fallbackPlacements","shift","whileElementsMounted","autoUpdate","click","useClick","enabled","hover","useHover","focus","useFocus","dismiss","useDismiss","role","useRole","interactions","useInteractions","useLayoutEffect","refs","setPositionReference","current","useMemo","usePopover","Provider","value","PopoverTrigger","forwardRef","asChild","props","propRef","getReferenceProps","childrenRef","ref","useMergeRefs","setReference","isValidElement","cloneElement","jsx","onClick","PopoverContent","style","className","initialFocus","returnFocus","floatingStyles","getFloatingProps","setFloating","referenceElement","reference","theme","size","getThemeAndSize","contextElement","floatingPortalRef","useRef","useEffect","elements","domReference","closest","document","body","FloatingPortal","root","FloatingFocusManager","clsx","Trigger","Content"],"mappings":"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"}
1
+ {"version":3,"file":"Popover.cjs","sources":["../../../../src/components/popover/Popover.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n FloatingPortal,\n type ReferenceElement,\n type VirtualElement,\n autoUpdate,\n flip,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n useMergeRefs,\n useRole,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport * as React from \"react\";\nimport { getThemeAndSize } from \"../../utilities/getThemeAndSize.js\";\nimport type { PopoverOptions } from \"./types.js\";\n\nconst usePopover = ({\n open: _open,\n onOpenChange: _onOpenChange,\n placement = \"bottom-start\",\n strategy = \"absolute\",\n modal = true,\n offset: _offset = 4,\n positionReference,\n hoverOptions,\n focusOptions,\n clickOptions,\n roleOptions,\n dismissOptions,\n}: PopoverOptions) => {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(_open);\n\n const open = _open ?? uncontrolledOpen;\n const onOpenChange = _onOpenChange ?? setUncontrolledOpen;\n\n const data = useFloating({\n open,\n onOpenChange,\n placement,\n strategy,\n middleware: [\n offset(_offset),\n flip({ padding: 5, fallbackPlacements: [\"bottom\", \"top\"] }),\n shift({ padding: 12 }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const context = data.context;\n\n const click = useClick(context, {\n enabled: false,\n ...clickOptions,\n });\n const hover = useHover(context, { enabled: false, ...hoverOptions });\n const focus = useFocus(context, { enabled: false, ...focusOptions });\n const dismiss = useDismiss(context, dismissOptions);\n const role = useRole(context, roleOptions);\n\n const interactions = useInteractions([click, dismiss, focus, hover, role]);\n\n React.useLayoutEffect(() => {\n if (positionReference) {\n data.refs.setPositionReference(positionReference?.current);\n }\n }, [positionReference, data.refs]);\n\n return React.useMemo(\n () => ({\n open,\n onOpenChange,\n modal,\n ...interactions,\n ...data,\n }),\n [open, onOpenChange, modal, interactions, data],\n );\n};\n\ntype PopoverContextType = ReturnType<typeof usePopover> | null;\n\nconst PopoverContext = React.createContext<PopoverContextType>(null);\n\nconst usePopoverContext = () => {\n const context = React.useContext(PopoverContext);\n\n if (context == null) {\n throw new Error(\n \"Popover komponenter må brukes innenfor en <Popover /> komponent\",\n );\n }\n\n return context;\n};\n\nexport const Popover = ({\n children,\n ...restOptions\n}: {\n children: React.ReactNode;\n} & PopoverOptions) => {\n const popover = usePopover({ ...restOptions });\n return (\n <PopoverContext.Provider value={popover}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\ninterface PopoverTriggerProps {\n children: React.ReactNode;\n /**\n * Rendrer komponenten som child-elementet sitt, og slår sammen egenskaper og props.\n *\n * Default er `false`.\n *\n * @example\n * ```tsx\n * <Component asChild foo=\"bar\">\n * <Child baz=\"qux\" />\n * </Component>\n *\n * // Rendrer følgende:\n * <Child foo=\"bar\" baz=\"qux\" />\n * ```\n */\n asChild?: boolean;\n}\n\nconst PopoverTrigger = React.forwardRef<\n HTMLElement,\n React.HTMLProps<HTMLElement> & PopoverTriggerProps\n>(function PopoverTrigger({ children, asChild = false, ...props }, propRef) {\n const { refs, getReferenceProps, open, onOpenChange } = usePopoverContext();\n const childrenRef = (children as any).ref;\n const ref = useMergeRefs([refs.setReference, propRef, childrenRef]);\n\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(\n children,\n getReferenceProps({\n ref,\n ...props,\n ...children.props,\n }),\n );\n }\n\n return (\n <button\n ref={ref}\n onClick={() => onOpenChange?.(!open)}\n aria-expanded={open}\n {...getReferenceProps({\n ...props,\n className: clsx(\"jkl-popover-trigger\", props.className),\n })}\n >\n {children}\n </button>\n );\n});\n\ninterface PopoverContentProps {\n /**\n * Padding rundt innholdet i popoveren.\n *\n * Default er `0`.\n */\n padding?: 0 | 8 | 16 | 24;\n /**\n *\n * Angir hvilket element som skal motta fokus ved åpning.\n * Kan være en tabbar index eller en referanse til et element.\"\n *\n * Default er `0`, som betyr at det første fokuserbare elementet i popoveren får fokus.\n * @see https://floating-ui.com/docs/FloatingFocusManager#initialfocus\n */\n initialFocus?: number | React.RefObject<HTMLElement>;\n /**\n * Angir om fokus skal returneres til triggeren når popoveren lukkes.\n *\n * Default er `true`.\n * @see https://floating-ui.com/docs/FloatingFocusManager#returnfocus\n */\n returnFocus?: boolean;\n}\n\n// Er popover-elementet posisjonert i forhold til et annet element enn triggeren?\nconst isCustomPositioned = (\n referenceElement: ReferenceElement,\n): referenceElement is VirtualElement => {\n if (!referenceElement) return false;\n\n return \"contextElement\" in referenceElement;\n};\n\nconst PopoverContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLProps<HTMLDivElement> & PopoverContentProps\n>(function PopoverContent(\n {\n style,\n className,\n padding = 0,\n initialFocus = 0,\n returnFocus = true,\n ...props\n },\n propRef,\n) {\n const { context, modal, refs, open, floatingStyles, getFloatingProps } =\n usePopoverContext();\n const ref = useMergeRefs([refs.setFloating, propRef]);\n\n const referenceElement = refs.reference.current as ReferenceElement;\n\n const { theme, size } = isCustomPositioned(referenceElement)\n ? getThemeAndSize(referenceElement.contextElement)\n : getThemeAndSize(referenceElement);\n\n const floatingPortalRef = React.useRef<HTMLElement | null>(null);\n\n // TODO: Løser et problem hvor nestede portaler ikke \"fester\" seg til det nærmeste portal-elementet. Fjernes når alle komponenter som rendres i en portal tar i bruk popover komponenten da den håndterer dette internt. Issue: https://github.com/fremtind/jokul/issues/4356\n React.useEffect(() => {\n floatingPortalRef.current =\n context.elements.domReference?.closest<HTMLElement>(\n \"[data-portal]\",\n ) || document.body;\n }, [context.elements.domReference]);\n\n if (!open) return null;\n\n return (\n <FloatingPortal root={floatingPortalRef.current}>\n <FloatingFocusManager\n context={context}\n modal={modal}\n initialFocus={initialFocus}\n returnFocus={returnFocus}\n >\n <div\n data-theme={theme}\n data-size={size}\n className={clsx(\"jkl jkl-popover\", className)}\n ref={ref}\n style={\n {\n ...style,\n ...floatingStyles,\n \"--popover-padding\": `var(--jkl-spacing-${padding})`,\n } as React.CSSProperties\n }\n {...getFloatingProps(props)}\n >\n {props.children}\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n );\n});\n\nPopover.Trigger = PopoverTrigger;\nPopover.Content = PopoverContent;\n\nexport default Popover;\n"],"names":["PopoverContext","React","createContext","usePopoverContext","context","useContext","Error","Popover","children","restOptions","popover","open","_open","onOpenChange","_onOpenChange","placement","strategy","modal","offset","_offset","positionReference","hoverOptions","focusOptions","clickOptions","roleOptions","dismissOptions","uncontrolledOpen","setUncontrolledOpen","useState","data","useFloating","middleware","flip","padding","fallbackPlacements","shift","whileElementsMounted","autoUpdate","click","useClick","enabled","hover","useHover","focus","useFocus","dismiss","useDismiss","role","useRole","interactions","useInteractions","useLayoutEffect","refs","setPositionReference","current","useMemo","usePopover","Provider","value","PopoverTrigger","forwardRef","asChild","props","propRef","getReferenceProps","childrenRef","ref","useMergeRefs","setReference","isValidElement","cloneElement","jsx","onClick","className","clsx","PopoverContent","style","initialFocus","returnFocus","floatingStyles","getFloatingProps","setFloating","referenceElement","reference","theme","size","getThemeAndSize","contextElement","floatingPortalRef","useRef","useEffect","elements","domReference","closest","document","body","FloatingPortal","root","FloatingFocusManager","Trigger","Content"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import{c as a}from"../../../clsx-BeLtu-UY.js";import{d as r,g as o}from"../../../utils-CcE6HjQp.js";import{forwardRef as n,useState as l,useRef as s,useCallback as i}from"react";import{flushSync as u}from"react-dom";import{IconButton as d}from"../icon-button/IconButton.js";import{CalendarIcon as c}from"../icon/icons/CalendarIcon.js";import{InputGroup as p}from"../input-group/InputGroup.js";import{Popover as m}from"../popover/Popover.js";import{BaseTextInput as f}from"../text-input/BaseTextInput.js";import{Calendar as v}from"./internal/Calendar.js";import{parseDateString as h,formatInput as b}from"./utils.js";import{isWithinLowerBound as k,isWithinUpperBound as D}from"./validation.js";const g=n((n,g)=>{const{"data-testautoid":j,id:y,className:L="",label:w="Velg dato",labelProps:C,defaultValue:x,defaultShow:I=!1,value:P,disableBeforeDate:B,disableAfterDate:O,yearsToShow:_,name:E,helpLabel:T,errorLabel:N,invalid:S,days:R,months:U,monthLabel:V,yearLabel:F,placeholder:K="dd.mm.åååå",width:W="11.25rem",onChange:A,onBlur:G,onFocus:q,onKeyDown:H,action:M,showCalendarLabel:z="Åpne kalender",hideCalendarLabel:J="Lukk kalender",supportLabelProps:Q,tooltip:X,textInputProps:Y,description:Z,...$}=n;"production"!==process.env.NODE_ENV&&P&&x&&console.warn("DatePicker må enten være controlled eller uncontrolled. Hvis du bruker defaultValue og value sammen vil defaultValue bli ignorert.");const ee=h(B),te=ee?r(ee).startOf("day").toDate():void 0,ae=h(O),re=ae?r(ae).startOf("day").toDate():void 0,[oe,ne]=l(o(P,x,te,re)),[le,se]=l(null),[ie,ue]=l(I),de=s(null),ce=s(null),pe=s(null),me=s(null),fe=i(e=>{me.current=e,g&&("function"==typeof g?g(e):g.current=e)},[g]),ve=i(e=>{q&&ce.current&&(ce.current.contains(e.relatedTarget)||q(e,oe,{error:le,value:e.target.value}))},[q,oe,le]),he=i(e=>{G&&G(e,oe,{error:le,value:e.target.value})},[G,oe,le]),be=i(e=>{"Escape"===e.key&&(ue(!1),e.preventDefault(),e.stopPropagation()),M?.onKeyDown&&M.onKeyDown(e)},[M]),ke=i(e=>{let t=null,a=null;if(e.target.value){const r=h(e.target.value);r?te&&!k(r,te)?a="OUTSIDE_LOWER_BOUND":re&&!D(r,re)?a="OUTSIDE_UPPER_BOUND":ue(!1):a="WRONG_FORMAT",t=r||null}se(a),ne(t),A&&A(e,t,{error:a,value:e.target.value})},[A,te,re]),De=i(e=>{u(()=>{ue(!ie)});const t=de.current,a=t&&t.querySelector('[aria-pressed="true"]');window.requestAnimationFrame(()=>a?.focus()),M?.onClick&&M.onClick(e)},[ie,M]),ge=i(({date:e})=>{if(ue(!1),ne(e),me.current){const t=me.current;t.value=b(e);const a=document.createEvent("HTMLEvents");a.initEvent("input",!0,!1),t.dispatchEvent(a),t.focus(),A&&A(a,e,{error:null,value:t.value})}},[A]),je=i(e=>{e.preventDefault(),ue(!1),pe.current?.focus()},[]);return e(p,{id:y,className:a("jkl-datepicker",L),...$,ref:ce,label:w,labelProps:C,helpLabel:T,errorLabel:N,supportLabelProps:Q,tooltip:X,description:Z,render:a=>e(f,{"data-focused":ie?"true":void 0,ref:fe,"data-testid":"jkl-datepicker__input","data-testautoid":j,className:"jkl-datepicker__input",name:E,defaultValue:x,value:P,type:"text",placeholder:K,width:W,onFocus:ve,onBlur:he,onChange:ke,actionButton:t(m,{positionReference:me,open:ie,onOpenChange:()=>ue(!ie),offset:8,children:[e(m.Trigger,{...M,"data-testid":"jkl-datepicker__trigger",className:"jkl-text-input-action-button",title:ie?J:z,tabIndex:0,onClick:De,onKeyDown:be,asChild:!0,children:e(d,{children:e(c,{})})}),e(m.Content,{initialFocus:-1,padding:24,children:e(v,{ref:de,date:oe,minDate:te,maxDate:re,days:R,months:U,monthLabel:V,yearLabel:F,yearsToShow:_,onDateSelected:ge,onTabOutside:je})})]}),...Y,...a,"aria-invalid":S||!!N})})});g.displayName="DatePicker";export{g as DatePicker};
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import{c as a}from"../../../clsx-BeLtu-UY.js";import{d as r,g as o}from"../../../utils-CcE6HjQp.js";import{forwardRef as n,useState as l,useRef as s,useCallback as i}from"react";import{flushSync as u}from"react-dom";import{formatDateString as d}from"../../utilities/formatters/date/formatDate.js";import{IconButton as c}from"../icon-button/IconButton.js";import{CalendarIcon as p}from"../icon/icons/CalendarIcon.js";import{InputGroup as m}from"../input-group/InputGroup.js";import{Popover as f}from"../popover/Popover.js";import{BaseTextInput as v}from"../text-input/BaseTextInput.js";import{Calendar as D}from"./internal/Calendar.js";import{parseDateString as h,formatInput as b}from"./utils.js";import{isWithinLowerBound as g,isWithinUpperBound as k}from"./validation.js";const j=n((n,j)=>{const{"data-testautoid":y,id:L,className:w="",label:x="Velg dato",labelProps:C,defaultValue:I,defaultShow:O=!1,value:P,disableBeforeDate:T,disableAfterDate:B,yearsToShow:E,name:_,helpLabel:S,errorLabel:N,invalid:R,days:U,months:V,monthLabel:F,yearLabel:K,placeholder:W="dd.mm.åååå",width:A="11.25rem",onChange:G,onBlur:H,onFocus:M,onKeyDown:q,action:$,showCalendarLabel:z="Åpne kalender",hideCalendarLabel:J="Lukk kalender",supportLabelProps:Q,tooltip:X,textInputProps:Y,description:Z,...ee}=n;"production"!==process.env.NODE_ENV&&P&&I&&console.warn("DatePicker må enten være controlled eller uncontrolled. Hvis du bruker defaultValue og value sammen vil defaultValue bli ignorert.");const te=h(T),ae=te?r(te).startOf("day").toDate():void 0,re=h(B),oe=re?r(re).startOf("day").toDate():void 0,[ne,le]=l(o(P,I,ae,oe)),[se,ie]=l(null),[ue,de]=l(O),ce=s(null),pe=s(null),me=s(null),fe=s(null),ve=i(e=>{fe.current=e,j&&("function"==typeof j?j(e):j.current=e)},[j]),De=i(e=>{M&&pe.current&&(pe.current.contains(e.relatedTarget)||M(e,ne,{error:se,value:e.target.value}))},[M,ne,se]),he=i(e=>{H&&H(e,ne,{error:se,value:e.target.value})},[H,ne,se]),be=i(e=>{"Escape"===e.key&&(de(!1),e.preventDefault(),e.stopPropagation()),$?.onKeyDown&&$.onKeyDown(e)},[$]),ge=i(e=>{const t=e.currentTarget.value,a=(e=>{const t=e.replace(/\D/g,""),a=d(t,{partial:!0}),r=e.replace(/\D+$/,""),o=8===t.length?d(t):e,n=h(o)?o:null,l=e!==t&&r===a&&void 0===h(e)&&null===n;return n??(l?t:e)})(t);a!==t&&((e,t)=>{const a=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"value")?.set;a?a.call(e,t):e.value=t})(e.currentTarget,a);const{date:r,error:o}=(({value:e,minDate:t,maxDate:a})=>{if(!e)return{date:null,error:null};const r=h(e);return r?t&&!g(r,t)?{date:r,error:"OUTSIDE_LOWER_BOUND"}:a&&!k(r,a)?{date:r,error:"OUTSIDE_UPPER_BOUND"}:{date:r,error:null}:{date:null,error:"WRONG_FORMAT"}})({value:a,minDate:ae,maxDate:oe});r&&!o&&de(!1),ie(o),le(r),G&&G(e,r,{error:o,value:a})},[G,ae,oe]),ke=i(e=>{u(()=>{de(!ue)});const t=ce.current,a=t&&t.querySelector('[aria-pressed="true"]');window.requestAnimationFrame(()=>a?.focus()),$?.onClick&&$.onClick(e)},[ue,$]),je=i(({date:e})=>{if(de(!1),le(e),fe.current){const t=fe.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})}},[G]),ye=i(e=>{e.preventDefault(),de(!1),me.current?.focus()},[]);return e(m,{id:L,className:a("jkl-datepicker",w),...ee,ref:pe,label:x,labelProps:C,helpLabel:S,errorLabel:N,supportLabelProps:Q,tooltip:X,description:Z,render:a=>e(v,{"data-focused":ue?"true":void 0,ref:ve,"data-testid":"jkl-datepicker__input","data-testautoid":y,className:"jkl-datepicker__input",name:_,defaultValue:I,value:P,type:"text",placeholder:W,width:A,onFocus:De,onBlur:he,onChange:ge,actionButton:t(f,{positionReference:fe,open:ue,onOpenChange:()=>de(!ue),offset:8,children:[e(f.Trigger,{...$,"data-testid":"jkl-datepicker__trigger",className:"jkl-text-input-action-button",title:ue?J:z,tabIndex:0,onClick:ke,onKeyDown:be,asChild:!0,children:e(c,{children:e(p,{})})}),e(f.Content,{initialFocus:-1,padding:24,children:e(D,{ref:ce,date:ne,minDate:ae,maxDate:oe,days:U,months:V,monthLabel:F,yearLabel:K,yearsToShow:E,onDateSelected:je,onTabOutside:ye})})]}),...Y,...a,"aria-invalid":R||!!N})})});j.displayName="DatePicker";export{j 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 dayjs from \"dayjs\";\nimport React, {\n type ChangeEvent,\n type FocusEvent,\n type KeyboardEvent,\n type MouseEvent,\n forwardRef,\n useCallback,\n useRef,\n useState,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { CalendarIcon } from \"../icon/icons/CalendarIcon.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 { type DateInfo, getInitialDate } from \"./internal/utils.js\";\nimport type { 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 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 tooltip,\n textInputProps,\n description,\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 ? dayjs(disableBeforeDate).startOf(\"day\").toDate()\n : undefined;\n const disableAfterDate = parseDateString(disableAfter);\n const maxDate = disableAfterDate\n ? dayjs(disableAfterDate).startOf(\"day\").toDate()\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 [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 [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, 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?.focus());\n\n if (action?.onClick) {\n action.onClick(e);\n }\n },\n [showCalendar, action],\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 [onChange],\n );\n\n const handleTabOutsideCalendar = useCallback((e: KeyboardEvent) => {\n e.preventDefault();\n setShowCalendar(false);\n iconButtonRef.current?.focus();\n }, []);\n\n return (\n <InputGroup\n id={id}\n className={clsx(\"jkl-datepicker\", className)}\n {...rest}\n ref={datepickerRef}\n label={label}\n labelProps={labelProps}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n supportLabelProps={supportLabelProps}\n tooltip={tooltip}\n description={description}\n render={(inputProps) => (\n <BaseTextInput\n data-focused={showCalendar ? \"true\" : undefined}\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 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 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 {...textInputProps}\n {...inputProps}\n aria-invalid={invalid || !!errorLabel}\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","days","months","monthLabel","yearLabel","placeholder","width","onChange","onBlur","onFocus","onKeyDown","action","showCalendarLabel","hideCalendarLabel","supportLabelProps","tooltip","textInputProps","description","rest","process","env","NODE_ENV","console","warn","parseDateString","minDate","dayjs","startOf","toDate","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 dayjs from \"dayjs\";\nimport React, {\n type ChangeEvent,\n type FocusEvent,\n type KeyboardEvent,\n type MouseEvent,\n forwardRef,\n useCallback,\n useRef,\n useState,\n} from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { formatDateString } from \"../../utilities/formatters/date/formatDate.js\";\nimport { IconButton } from \"../icon-button/IconButton.js\";\nimport { CalendarIcon } from \"../icon/icons/CalendarIcon.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 { type DateInfo, getInitialDate } from \"./internal/utils.js\";\nimport type { DatePickerProps, DateValidationError } from \"./types.js\";\nimport { formatInput, parseDateString } from \"./utils.js\";\nimport { isWithinLowerBound, isWithinUpperBound } from \"./validation.js\";\n\nconst setInputValue = (input: HTMLInputElement, value: string) => {\n const nativeSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n \"value\",\n )?.set;\n\n if (nativeSetter) {\n nativeSetter.call(input, value);\n } else {\n input.value = value;\n }\n};\n\nconst normalizeInputValue = (rawValue: string) => {\n const digits = rawValue.replace(/\\D/g, \"\");\n const partialCompactDate = formatDateString(digits, {\n partial: true,\n });\n const rawValueWithoutTrailingPunctuation = rawValue.replace(/\\D+$/, \"\");\n const compactDateCandidate =\n digits.length === 8 ? formatDateString(digits) : rawValue;\n const validCompactDate = parseDateString(compactDateCandidate)\n ? compactDateCandidate\n : null;\n const shouldRemoveFormatting =\n rawValue !== digits &&\n rawValueWithoutTrailingPunctuation === partialCompactDate &&\n parseDateString(rawValue) === undefined &&\n validCompactDate === null;\n\n return validCompactDate ?? (shouldRemoveFormatting ? digits : rawValue);\n};\n\nconst getInputValidationState = ({\n value,\n minDate,\n maxDate,\n}: {\n value: string;\n minDate?: Date;\n maxDate?: Date;\n}): { date: Date | null; error: DateValidationError | null } => {\n if (!value) {\n return { date: null, error: null };\n }\n\n const parsedDate = parseDateString(value);\n\n if (!parsedDate) {\n return { date: null, error: \"WRONG_FORMAT\" };\n }\n\n if (minDate && !isWithinLowerBound(parsedDate, minDate)) {\n return { date: parsedDate, error: \"OUTSIDE_LOWER_BOUND\" };\n }\n\n if (maxDate && !isWithinUpperBound(parsedDate, maxDate)) {\n return { date: parsedDate, error: \"OUTSIDE_UPPER_BOUND\" };\n }\n\n return { date: parsedDate, error: null };\n};\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 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 tooltip,\n textInputProps,\n description,\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 ? dayjs(disableBeforeDate).startOf(\"day\").toDate()\n : undefined;\n const disableAfterDate = parseDateString(disableAfter);\n const maxDate = disableAfterDate\n ? dayjs(disableAfterDate).startOf(\"day\").toDate()\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 [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 [action],\n );\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n const rawValue = e.currentTarget.value;\n const formattedValue = normalizeInputValue(rawValue);\n\n if (formattedValue !== rawValue) {\n setInputValue(e.currentTarget, formattedValue);\n }\n\n const { date: nextDate, error: nextError } =\n getInputValidationState({\n value: formattedValue,\n minDate,\n maxDate,\n });\n\n if (nextDate && !nextError) {\n setShowCalendar(false);\n }\n\n setError(nextError);\n setDate(nextDate);\n\n if (onChange) {\n onChange(e, nextDate, {\n error: nextError,\n value: formattedValue,\n });\n }\n },\n [onChange, 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?.focus());\n\n if (action?.onClick) {\n action.onClick(e);\n }\n },\n [showCalendar, action],\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 [onChange],\n );\n\n const handleTabOutsideCalendar = useCallback((e: KeyboardEvent) => {\n e.preventDefault();\n setShowCalendar(false);\n iconButtonRef.current?.focus();\n }, []);\n\n return (\n <InputGroup\n id={id}\n className={clsx(\"jkl-datepicker\", className)}\n {...rest}\n ref={datepickerRef}\n label={label}\n labelProps={labelProps}\n helpLabel={helpLabel}\n errorLabel={errorLabel}\n supportLabelProps={supportLabelProps}\n tooltip={tooltip}\n description={description}\n render={(inputProps) => (\n <BaseTextInput\n data-focused={showCalendar ? \"true\" : undefined}\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 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 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 {...textInputProps}\n {...inputProps}\n aria-invalid={invalid || !!errorLabel}\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","days","months","monthLabel","yearLabel","placeholder","width","onChange","onBlur","onFocus","onKeyDown","action","showCalendarLabel","hideCalendarLabel","supportLabelProps","tooltip","textInputProps","description","rest","process","env","NODE_ENV","console","warn","parseDateString","minDate","dayjs","startOf","toDate","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","rawValue","currentTarget","formattedValue","digits","replace","partialCompactDate","formatDateString","partial","rawValueWithoutTrailingPunctuation","compactDateCandidate","length","validCompactDate","shouldRemoveFormatting","normalizeInputValue","input","nativeSetter","Object","getOwnPropertyDescriptor","HTMLInputElement","prototype","set","call","setInputValue","nextDate","nextError","parsedDate","isWithinLowerBound","isWithinUpperBound","getInputValidationState","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{jsxs as e,jsx as t}from"react/jsx-runtime";import{c as a}from"../../../clsx-BeLtu-UY.js";import n,{useState as r,useRef as s,useImperativeHandle as o,useEffect as i}from"react";import{ExpandablePanelContent as l}from"./ExpandablePanelContent.js";import{ExpanderContext as d}from"./context.js";import{Expander as p}from"./Expander.js";const c=Object.assign(n.forwardRef(function(n,l){const{children:p,as:c="details",variant:m="fill",open:x,defaultOpen:f,onOpenChange:u,className:j,...v}=n,[E,b]=r(f||!1),[g,h]=r(!1),[k,C]=r(0),N=s();o(l,()=>N.current,[]);const P=c,_=typeof x<"u",w=_?x:E;return i(()=>{const e=e=>{b("open"===e.newState)},t=N.current;return t?.addEventListener("toggle",e),()=>t?.removeEventListener("toggle",e)},[]),e("div",{className:"jkl-expandable__wrapper",children:[t("div",{ref:e=>e?.setAttribute("inert","true"),className:"jkl-expandable__focus-container",style:{height:k}}),t(P,{ref:N,"data-testid":"jkl-expand-section",className:a("jkl-expandable",`jkl-expandable--${m}`,j),open:"details"===c?w||g:void 0,"data-visible-content":w||g,...v,children:t(d.Provider,{value:{open:w,onToggle:()=>{_||b(e=>(u?.(!e),!e))},onTransitionEnd:h,onTransitionStart:e=>{e&&h(!0)},setExpanderHeight:C},children:p})})]})}),{Content:l,Header:p});export{c as ExpandablePanel};
1
+ import{jsxs as e,jsx as t}from"react/jsx-runtime";import{c as a}from"../../../clsx-BeLtu-UY.js";import n,{useState as r,useRef as s,useImperativeHandle as o,useEffect as i}from"react";import{ExpandablePanelContent as l}from"./ExpandablePanelContent.js";import{Expander as d}from"./Expander.js";import{ExpanderContext as p}from"./context.js";const c=Object.assign(n.forwardRef(function(n,l){const{children:d,as:c="details",variant:m="fill",open:x,defaultOpen:f,onOpenChange:u,className:j,...v}=n,[E,b]=r(f||!1),[g,h]=r(!1),[k,C]=r(0),N=s();o(l,()=>N.current,[]);const P=c,_=typeof x<"u",w=_?x:E;return i(()=>{const e=e=>{b("open"===e.newState)},t=N.current;return t?.addEventListener("toggle",e),()=>t?.removeEventListener("toggle",e)},[]),e("div",{className:"jkl-expandable__wrapper",children:[t("div",{ref:e=>e?.setAttribute("inert","true"),className:"jkl-expandable__focus-container",style:{height:k}}),t(P,{ref:N,"data-testid":"jkl-expand-section",className:a("jkl-expandable",`jkl-expandable--${m}`,j),open:"details"===c?w||g:void 0,"data-visible-content":w||g,...v,children:t(p.Provider,{value:{open:w,onToggle:()=>{_?u?.(!w):b(e=>(u?.(!e),!e))},onTransitionEnd:h,onTransitionStart:e=>{e&&h(!0)},setExpanderHeight:C},children:d})})]})}),{Content:l,Header:d});export{c as ExpandablePanel};
2
2
  //# sourceMappingURL=ExpandablePanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpandablePanel.js","sources":["../../../../src/components/expander/ExpandablePanel.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport type { PolymorphicRef } from \"../../utilities/polymorphism/polymorphism.js\";\nimport { ExpandablePanelContent } from \"./ExpandablePanelContent.js\";\nimport { ExpanderContext } from \"./context.js\";\nimport type {\n ExpandablePanelComponent,\n ExpandablePanelProps,\n} from \"./types.js\";\nimport { Expander } from \"./Expander.jsx\";\n\nexport const ExpandablePanel = Object.assign(\n React.forwardRef(function ExpandablePanel<\n ElementType extends React.ElementType = \"details\",\n >(\n props: ExpandablePanelProps<ElementType>,\n ref?: PolymorphicRef<ElementType>,\n ) {\n const {\n children,\n as = \"details\",\n variant = \"fill\",\n open: controlledOpen,\n defaultOpen,\n onOpenChange,\n className,\n ...rest\n } = props;\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(\n defaultOpen || false,\n );\n const [contentIsVisible, setContentIsVisible] = useState(false);\n const [expanderHeight, setExpanderHeight] = useState(0);\n\n const internalRef = useRef<HTMLDetailsElement>();\n useImperativeHandle(ref, () => internalRef.current, []);\n\n const El = as;\n const isControlled = typeof controlledOpen !== \"undefined\";\n const isOpen = isControlled ? controlledOpen : uncontrolledOpen;\n\n const setVisibleIfOpening = (isOpening: boolean) => {\n if (isOpening) {\n setContentIsVisible(true);\n }\n };\n\n const syncUncontrolledState = () => {\n if (isControlled) {\n return;\n }\n setUncontrolledOpen((previousValue) => {\n onOpenChange?.(!previousValue);\n return !previousValue;\n });\n };\n\n useEffect(() => {\n const callback = (e: ToggleEvent & { newState: string }) => {\n setUncontrolledOpen(e.newState === \"open\");\n };\n\n const element = internalRef.current;\n\n element?.addEventListener(\"toggle\", callback as EventListener);\n\n return () =>\n element?.removeEventListener(\n \"toggle\",\n callback as EventListener,\n );\n }, []);\n\n return (\n <div className=\"jkl-expandable__wrapper\">\n <div\n /*\n Setter `inert` manuelt for å støtte både React 18 og 19.\n\n Dette unngår typefeil i React 18 og advarsler i React 19.\n Se: https://github.com/WICG/inert/issues/58\n */\n ref={(node) => node?.setAttribute(\"inert\", \"true\")}\n className=\"jkl-expandable__focus-container\"\n style={{ height: expanderHeight }}\n />\n <El\n ref={internalRef}\n data-testid={\"jkl-expand-section\"}\n className={clsx(\n \"jkl-expandable\",\n `jkl-expandable--${variant}`,\n className,\n )}\n open={\n /* for the animation to work in Safari we must ensure that\n * the element is open *before* the transition starts */\n as === \"details\"\n ? isOpen || contentIsVisible\n : undefined\n }\n /* this attribute is used for styling purposes */\n data-visible-content={isOpen || contentIsVisible}\n {...rest}\n >\n <ExpanderContext.Provider\n value={{\n open: isOpen,\n onToggle: syncUncontrolledState,\n onTransitionEnd: setContentIsVisible,\n onTransitionStart: setVisibleIfOpening,\n setExpanderHeight,\n }}\n >\n {children}\n </ExpanderContext.Provider>\n </El>\n </div>\n );\n }),\n { Content: ExpandablePanelContent, Header: Expander },\n) as ExpandablePanelComponent;\n"],"names":["ExpandablePanel","Object","assign","React","forwardRef","props","ref","children","as","variant","open","controlledOpen","defaultOpen","onOpenChange","className","rest","uncontrolledOpen","setUncontrolledOpen","useState","contentIsVisible","setContentIsVisible","expanderHeight","setExpanderHeight","internalRef","useRef","useImperativeHandle","current","El","isControlled","isOpen","useEffect","callback","e","newState","element","addEventListener","removeEventListener","jsxs","jsx","node","setAttribute","style","height","clsx","ExpanderContext","Provider","value","onToggle","previousValue","onTransitionEnd","onTransitionStart","isOpening","Content","ExpandablePanelContent","Header","Expander"],"mappings":"qVAWO,MAAMA,EAAkBC,OAAOC,OAClCC,EAAMC,WAAW,SAGbC,EACAC,GAEA,MACIC,SAAAA,EACAC,GAAAA,EAAK,UACLC,QAAAA,EAAU,OACVC,KAAMC,EACNC,YAAAA,EACAC,aAAAA,EACAC,UAAAA,KACGC,GACHV,GAEGW,EAAkBC,GAAuBC,EAC5CN,IAAe,IAEZO,EAAkBC,GAAuBF,GAAS,IAClDG,EAAgBC,GAAqBJ,EAAS,GAE/CK,EAAcC,IACpBC,EAAoBnB,EAAK,IAAMiB,EAAYG,QAAS,IAEpD,MAAMC,EAAKnB,EACLoB,SAAsBjB,EAAmB,IACzCkB,EAASD,EAAejB,EAAiBK,EAkB/C,OAAAc,EAAU,KACN,MAAMC,EAAYC,IACdf,EAAmC,SAAfe,EAAEC,WAGpBC,EAAUX,EAAYG,QAE5B,OAAAQ,GAASC,iBAAiB,SAAUJ,GAE7B,IACHG,GAASE,oBACL,SACAL,IAET,IAGCM,EAAC,MAAA,CAAIvB,UAAU,0BACXP,SAAA,CAAA+B,EAAC,MAAA,CAOGhC,IAAMiC,GAASA,GAAMC,aAAa,QAAS,QAC3C1B,UAAU,kCACV2B,MAAO,CAAEC,OAAQrB,KAErBiB,EAACX,EAAA,CACGrB,IAAKiB,EACL,cAAa,qBACbT,UAAW6B,EACP,iBACA,mBAAmBlC,IACnBK,GAEJJ,KAGW,YAAPF,EACMqB,GAAUV,OACV,EAGV,uBAAsBU,GAAUV,KAC5BJ,EAEJR,SAAA+B,EAACM,EAAgBC,SAAhB,CACGC,MAAO,CACHpC,KAAMmB,EACNkB,SA7DU,KACtBnB,GAGJX,EAAqB+B,IACjBnC,KAAgBmC,IACRA,KAwDIC,gBAAiB7B,EACjB8B,kBArESC,IACrBA,GACA/B,GAAoB,IAoERE,kBAAAA,GAGHf,SAAAA,QAKrB,GACA,CAAE6C,QAASC,EAAwBC,OAAQC"}
1
+ {"version":3,"file":"ExpandablePanel.js","sources":["../../../../src/components/expander/ExpandablePanel.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\nimport type { PolymorphicRef } from \"../../utilities/polymorphism/polymorphism.js\";\nimport { ExpandablePanelContent } from \"./ExpandablePanelContent.js\";\nimport { Expander } from \"./Expander.jsx\";\nimport { ExpanderContext } from \"./context.js\";\nimport type {\n ExpandablePanelComponent,\n ExpandablePanelProps,\n} from \"./types.js\";\n\nexport const ExpandablePanel = Object.assign(\n React.forwardRef(function ExpandablePanel<\n ElementType extends React.ElementType = \"details\",\n >(\n props: ExpandablePanelProps<ElementType>,\n ref?: PolymorphicRef<ElementType>,\n ) {\n const {\n children,\n as = \"details\",\n variant = \"fill\",\n open: controlledOpen,\n defaultOpen,\n onOpenChange,\n className,\n ...rest\n } = props;\n\n const [uncontrolledOpen, setUncontrolledOpen] = useState(\n defaultOpen || false,\n );\n const [contentIsVisible, setContentIsVisible] = useState(false);\n const [expanderHeight, setExpanderHeight] = useState(0);\n\n const internalRef = useRef<HTMLDetailsElement>();\n useImperativeHandle(ref, () => internalRef.current, []);\n\n const El = as;\n const isControlled = typeof controlledOpen !== \"undefined\";\n const isOpen = isControlled ? controlledOpen : uncontrolledOpen;\n\n const setVisibleIfOpening = (isOpening: boolean) => {\n if (isOpening) {\n setContentIsVisible(true);\n }\n };\n\n const syncUncontrolledState = () => {\n if (isControlled) {\n onOpenChange?.(!isOpen);\n return;\n }\n setUncontrolledOpen((previousValue) => {\n onOpenChange?.(!previousValue);\n return !previousValue;\n });\n };\n\n useEffect(() => {\n const callback = (e: ToggleEvent & { newState: string }) => {\n setUncontrolledOpen(e.newState === \"open\");\n };\n\n const element = internalRef.current;\n\n element?.addEventListener(\"toggle\", callback as EventListener);\n\n return () =>\n element?.removeEventListener(\n \"toggle\",\n callback as EventListener,\n );\n }, []);\n\n return (\n <div className=\"jkl-expandable__wrapper\">\n <div\n /*\n Setter `inert` manuelt for å støtte både React 18 og 19.\n\n Dette unngår typefeil i React 18 og advarsler i React 19.\n Se: https://github.com/WICG/inert/issues/58\n */\n ref={(node) => node?.setAttribute(\"inert\", \"true\")}\n className=\"jkl-expandable__focus-container\"\n style={{ height: expanderHeight }}\n />\n <El\n ref={internalRef}\n data-testid={\"jkl-expand-section\"}\n className={clsx(\n \"jkl-expandable\",\n `jkl-expandable--${variant}`,\n className,\n )}\n open={\n /* for the animation to work in Safari we must ensure that\n * the element is open *before* the transition starts */\n as === \"details\"\n ? isOpen || contentIsVisible\n : undefined\n }\n /* this attribute is used for styling purposes */\n data-visible-content={isOpen || contentIsVisible}\n {...rest}\n >\n <ExpanderContext.Provider\n value={{\n open: isOpen,\n onToggle: syncUncontrolledState,\n onTransitionEnd: setContentIsVisible,\n onTransitionStart: setVisibleIfOpening,\n setExpanderHeight,\n }}\n >\n {children}\n </ExpanderContext.Provider>\n </El>\n </div>\n );\n }),\n { Content: ExpandablePanelContent, Header: Expander },\n) as ExpandablePanelComponent;\n"],"names":["ExpandablePanel","Object","assign","React","forwardRef","props","ref","children","as","variant","open","controlledOpen","defaultOpen","onOpenChange","className","rest","uncontrolledOpen","setUncontrolledOpen","useState","contentIsVisible","setContentIsVisible","expanderHeight","setExpanderHeight","internalRef","useRef","useImperativeHandle","current","El","isControlled","isOpen","useEffect","callback","e","newState","element","addEventListener","removeEventListener","jsxs","jsx","node","setAttribute","style","height","clsx","ExpanderContext","Provider","value","onToggle","previousValue","onTransitionEnd","onTransitionStart","isOpening","Content","ExpandablePanelContent","Header","Expander"],"mappings":"qVAWO,MAAMA,EAAkBC,OAAOC,OAClCC,EAAMC,WAAW,SAGbC,EACAC,GAEA,MACIC,SAAAA,EACAC,GAAAA,EAAK,UACLC,QAAAA,EAAU,OACVC,KAAMC,EACNC,YAAAA,EACAC,aAAAA,EACAC,UAAAA,KACGC,GACHV,GAEGW,EAAkBC,GAAuBC,EAC5CN,IAAe,IAEZO,EAAkBC,GAAuBF,GAAS,IAClDG,EAAgBC,GAAqBJ,EAAS,GAE/CK,EAAcC,IACpBC,EAAoBnB,EAAK,IAAMiB,EAAYG,QAAS,IAEpD,MAAMC,EAAKnB,EACLoB,SAAsBjB,EAAmB,IACzCkB,EAASD,EAAejB,EAAiBK,EAmB/C,OAAAc,EAAU,KACN,MAAMC,EAAYC,IACdf,EAAmC,SAAfe,EAAEC,WAGpBC,EAAUX,EAAYG,QAE5B,OAAAQ,GAASC,iBAAiB,SAAUJ,GAE7B,IACHG,GAASE,oBACL,SACAL,IAET,IAGCM,EAAC,MAAA,CAAIvB,UAAU,0BACXP,SAAA,CAAA+B,EAAC,MAAA,CAOGhC,IAAMiC,GAASA,GAAMC,aAAa,QAAS,QAC3C1B,UAAU,kCACV2B,MAAO,CAAEC,OAAQrB,KAErBiB,EAACX,EAAA,CACGrB,IAAKiB,EACL,cAAa,qBACbT,UAAW6B,EACP,iBACA,mBAAmBlC,IACnBK,GAEJJ,KAGW,YAAPF,EACMqB,GAAUV,OACV,EAGV,uBAAsBU,GAAUV,KAC5BJ,EAEJR,SAAA+B,EAACM,EAAgBC,SAAhB,CACGC,MAAO,CACHpC,KAAMmB,EACNkB,SA9DU,KACtBnB,EACAf,KAAgBgB,GAGpBZ,EAAqB+B,IACjBnC,KAAgBmC,IACRA,KAwDIC,gBAAiB7B,EACjB8B,kBAtESC,IACrBA,GACA/B,GAAoB,IAqERE,kBAAAA,GAGHf,SAAAA,QAKrB,GACA,CAAE6C,QAASC,EAAwBC,OAAQC"}
@@ -1,2 +1,2 @@
1
- import{jsx as e}from"react/jsx-runtime";import{useMergeRefs as t,FloatingPortal as n,FloatingFocusManager as o,useFloating as s,autoUpdate as r,offset as a,flip as i,shift as l,useClick as c,useHover as u,useFocus as d,useDismiss as p,useRole as f,useInteractions as m}from"@floating-ui/react";import{c as g}from"../../../clsx-BeLtu-UY.js";import*as h from"react";import{getThemeAndSize as v}from"../../utilities/getThemeAndSize.js";const x=h.createContext(null),F=()=>{const e=h.useContext(x);if(null==e)throw new Error("Popover komponenter må brukes innenfor en <Popover /> komponent");return e},R=({children:t,...n})=>{const o=(({open:e,onOpenChange:t,placement:n="bottom-start",strategy:o="absolute",modal:g=!0,offset:v=4,positionReference:x,hoverOptions:F,focusOptions:R,clickOptions:b,roleOptions:k,dismissOptions:C})=>{const[O,P]=h.useState(e),E=e??O,j=t??P,y=s({open:E,onOpenChange:j,placement:n,strategy:o,middleware:[a(v),i({padding:5,fallbackPlacements:["bottom","top"]}),l({padding:12})],whileElementsMounted:r}),w=y.context,z=c(w,{enabled:!1,...b}),M=u(w,{enabled:!1,...F}),S=d(w,{enabled:!1,...R}),T=p(w,C),A=f(w,k),N=m([z,T,S,M,A]);return h.useLayoutEffect(()=>{x&&y.refs.setPositionReference(x?.current)},[x,y.refs]),h.useMemo(()=>({open:E,onOpenChange:j,modal:g,...N,...y}),[E,j,g,N,y])})({...n});return e(x.Provider,{value:o,children:t})},b=h.forwardRef(function({children:n,asChild:o=!1,...s},r){const{refs:a,getReferenceProps:i,open:l,onOpenChange:c}=F(),u=n.ref,d=t([a.setReference,r,u]);return o&&h.isValidElement(n)?h.cloneElement(n,i({ref:d,...s,...n.props})):e("button",{ref:d,onClick:()=>c?.(!l),"aria-expanded":l,...i(s),children:n})}),k=h.forwardRef(function({style:s,className:r,padding:a=0,initialFocus:i=0,returnFocus:l=!0,...c},u){const{context:d,modal:p,refs:f,open:m,floatingStyles:x,getFloatingProps:R}=F(),b=t([f.setFloating,u]),k=f.reference.current,{theme:C,size:O}=v((E=k)&&"contextElement"in E?k.contextElement:k),P=h.useRef(null);var E;return h.useEffect(()=>{P.current=d.elements.domReference?.closest("[data-portal]")||document.body},[d.elements.domReference]),m?e(n,{root:P.current,children:e(o,{context:d,modal:p,initialFocus:i,returnFocus:l,children:e("div",{"data-theme":C,"data-size":O,className:g("jkl jkl-popover",r),ref:b,style:{...s,...x,"--popover-padding":`var(--jkl-spacing-${a})`},...R(c),children:c.children})})}):null});R.Trigger=b,R.Content=k;export{R as Popover,R as default};
1
+ import{jsx as e}from"react/jsx-runtime";import{useMergeRefs as t,FloatingPortal as n,FloatingFocusManager as o,useFloating as s,autoUpdate as r,offset as a,flip as i,shift as l,useClick as c,useHover as u,useFocus as p,useDismiss as d,useRole as f,useInteractions as m}from"@floating-ui/react";import{c as g}from"../../../clsx-BeLtu-UY.js";import*as h from"react";import{getThemeAndSize as v}from"../../utilities/getThemeAndSize.js";const x=h.createContext(null),k=()=>{const e=h.useContext(x);if(null==e)throw new Error("Popover komponenter må brukes innenfor en <Popover /> komponent");return e},F=({children:t,...n})=>{const o=(({open:e,onOpenChange:t,placement:n="bottom-start",strategy:o="absolute",modal:g=!0,offset:v=4,positionReference:x,hoverOptions:k,focusOptions:F,clickOptions:R,roleOptions:b,dismissOptions:C})=>{const[O,P]=h.useState(e),j=e??O,E=t??P,y=s({open:j,onOpenChange:E,placement:n,strategy:o,middleware:[a(v),i({padding:5,fallbackPlacements:["bottom","top"]}),l({padding:12})],whileElementsMounted:r}),w=y.context,z=c(w,{enabled:!1,...R}),M=u(w,{enabled:!1,...k}),N=p(w,{enabled:!1,...F}),S=d(w,C),T=f(w,b),A=m([z,S,N,M,T]);return h.useLayoutEffect(()=>{x&&y.refs.setPositionReference(x?.current)},[x,y.refs]),h.useMemo(()=>({open:j,onOpenChange:E,modal:g,...A,...y}),[j,E,g,A,y])})({...n});return e(x.Provider,{value:o,children:t})},R=h.forwardRef(function({children:n,asChild:o=!1,...s},r){const{refs:a,getReferenceProps:i,open:l,onOpenChange:c}=k(),u=n.ref,p=t([a.setReference,r,u]);return o&&h.isValidElement(n)?h.cloneElement(n,i({ref:p,...s,...n.props})):e("button",{ref:p,onClick:()=>c?.(!l),"aria-expanded":l,...i({...s,className:g("jkl-popover-trigger",s.className)}),children:n})}),b=h.forwardRef(function({style:s,className:r,padding:a=0,initialFocus:i=0,returnFocus:l=!0,...c},u){const{context:p,modal:d,refs:f,open:m,floatingStyles:x,getFloatingProps:F}=k(),R=t([f.setFloating,u]),b=f.reference.current,{theme:C,size:O}=v((j=b)&&"contextElement"in j?b.contextElement:b),P=h.useRef(null);var j;return h.useEffect(()=>{P.current=p.elements.domReference?.closest("[data-portal]")||document.body},[p.elements.domReference]),m?e(n,{root:P.current,children:e(o,{context:p,modal:d,initialFocus:i,returnFocus:l,children:e("div",{"data-theme":C,"data-size":O,className:g("jkl jkl-popover",r),ref:R,style:{...s,...x,"--popover-padding":`var(--jkl-spacing-${a})`},...F(c),children:c.children})})}):null});F.Trigger=R,F.Content=b;export{F as Popover,F as default};
2
2
  //# sourceMappingURL=Popover.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Popover.js","sources":["../../../../src/components/popover/Popover.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n FloatingPortal,\n type ReferenceElement,\n type VirtualElement,\n autoUpdate,\n flip,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n useMergeRefs,\n useRole,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport * as React from \"react\";\nimport { getThemeAndSize } from \"../../utilities/getThemeAndSize.js\";\nimport type { PopoverOptions } from \"./types.js\";\n\nconst usePopover = ({\n open: _open,\n onOpenChange: _onOpenChange,\n placement = \"bottom-start\",\n strategy = \"absolute\",\n modal = true,\n offset: _offset = 4,\n positionReference,\n hoverOptions,\n focusOptions,\n clickOptions,\n roleOptions,\n dismissOptions,\n}: PopoverOptions) => {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(_open);\n\n const open = _open ?? uncontrolledOpen;\n const onOpenChange = _onOpenChange ?? setUncontrolledOpen;\n\n const data = useFloating({\n open,\n onOpenChange,\n placement,\n strategy,\n middleware: [\n offset(_offset),\n flip({ padding: 5, fallbackPlacements: [\"bottom\", \"top\"] }),\n shift({ padding: 12 }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const context = data.context;\n\n const click = useClick(context, {\n enabled: false,\n ...clickOptions,\n });\n const hover = useHover(context, { enabled: false, ...hoverOptions });\n const focus = useFocus(context, { enabled: false, ...focusOptions });\n const dismiss = useDismiss(context, dismissOptions);\n const role = useRole(context, roleOptions);\n\n const interactions = useInteractions([click, dismiss, focus, hover, role]);\n\n React.useLayoutEffect(() => {\n if (positionReference) {\n data.refs.setPositionReference(positionReference?.current);\n }\n }, [positionReference, data.refs]);\n\n return React.useMemo(\n () => ({\n open,\n onOpenChange,\n modal,\n ...interactions,\n ...data,\n }),\n [open, onOpenChange, modal, interactions, data],\n );\n};\n\ntype PopoverContextType = ReturnType<typeof usePopover> | null;\n\nconst PopoverContext = React.createContext<PopoverContextType>(null);\n\nconst usePopoverContext = () => {\n const context = React.useContext(PopoverContext);\n\n if (context == null) {\n throw new Error(\n \"Popover komponenter må brukes innenfor en <Popover /> komponent\",\n );\n }\n\n return context;\n};\n\nexport const Popover = ({\n children,\n ...restOptions\n}: {\n children: React.ReactNode;\n} & PopoverOptions) => {\n const popover = usePopover({ ...restOptions });\n return (\n <PopoverContext.Provider value={popover}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\ninterface PopoverTriggerProps {\n children: React.ReactNode;\n /**\n * Rendrer komponenten som child-elementet sitt, og slår sammen egenskaper og props.\n *\n * Default er `false`.\n *\n * @example\n * ```tsx\n * <Component asChild foo=\"bar\">\n * <Child baz=\"qux\" />\n * </Component>\n *\n * // Rendrer følgende:\n * <Child foo=\"bar\" baz=\"qux\" />\n * ```\n */\n asChild?: boolean;\n}\n\nconst PopoverTrigger = React.forwardRef<\n HTMLElement,\n React.HTMLProps<HTMLElement> & PopoverTriggerProps\n>(function PopoverTrigger({ children, asChild = false, ...props }, propRef) {\n const { refs, getReferenceProps, open, onOpenChange } = usePopoverContext();\n const childrenRef = (children as any).ref;\n const ref = useMergeRefs([refs.setReference, propRef, childrenRef]);\n\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(\n children,\n getReferenceProps({\n ref,\n ...props,\n ...children.props,\n }),\n );\n }\n\n return (\n <button\n ref={ref}\n onClick={() => onOpenChange?.(!open)}\n aria-expanded={open}\n {...getReferenceProps(props)}\n >\n {children}\n </button>\n );\n});\n\ninterface PopoverContentProps {\n /**\n * Padding rundt innholdet i popoveren.\n *\n * Default er `0`.\n */\n padding?: 0 | 8 | 16 | 24;\n /**\n *\n * Angir hvilket element som skal motta fokus ved åpning.\n * Kan være en tabbar index eller en referanse til et element.\"\n *\n * Default er `0`, som betyr at det første fokuserbare elementet i popoveren får fokus.\n * @see https://floating-ui.com/docs/FloatingFocusManager#initialfocus\n */\n initialFocus?: number | React.RefObject<HTMLElement>;\n /**\n * Angir om fokus skal returneres til triggeren når popoveren lukkes.\n *\n * Default er `true`.\n * @see https://floating-ui.com/docs/FloatingFocusManager#returnfocus\n */\n returnFocus?: boolean;\n}\n\n// Er popover-elementet posisjonert i forhold til et annet element enn triggeren?\nconst isCustomPositioned = (\n referenceElement: ReferenceElement,\n): referenceElement is VirtualElement => {\n if (!referenceElement) return false;\n\n return \"contextElement\" in referenceElement;\n};\n\nconst PopoverContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLProps<HTMLDivElement> & PopoverContentProps\n>(function PopoverContent(\n {\n style,\n className,\n padding = 0,\n initialFocus = 0,\n returnFocus = true,\n ...props\n },\n propRef,\n) {\n const { context, modal, refs, open, floatingStyles, getFloatingProps } =\n usePopoverContext();\n const ref = useMergeRefs([refs.setFloating, propRef]);\n\n const referenceElement = refs.reference.current as ReferenceElement;\n\n const { theme, size } = isCustomPositioned(referenceElement)\n ? getThemeAndSize(referenceElement.contextElement)\n : getThemeAndSize(referenceElement);\n\n const floatingPortalRef = React.useRef<HTMLElement | null>(null);\n\n // TODO: Løser et problem hvor nestede portaler ikke \"fester\" seg til det nærmeste portal-elementet. Fjernes når alle komponenter som rendres i en portal tar i bruk popover komponenten da den håndterer dette internt. Issue: https://github.com/fremtind/jokul/issues/4356\n React.useEffect(() => {\n floatingPortalRef.current =\n context.elements.domReference?.closest<HTMLElement>(\n \"[data-portal]\",\n ) || document.body;\n }, [context.elements.domReference]);\n\n if (!open) return null;\n\n return (\n <FloatingPortal root={floatingPortalRef.current}>\n <FloatingFocusManager\n context={context}\n modal={modal}\n initialFocus={initialFocus}\n returnFocus={returnFocus}\n >\n <div\n data-theme={theme}\n data-size={size}\n className={clsx(\"jkl jkl-popover\", className)}\n ref={ref}\n style={\n {\n ...style,\n ...floatingStyles,\n \"--popover-padding\": `var(--jkl-spacing-${padding})`,\n } as React.CSSProperties\n }\n {...getFloatingProps(props)}\n >\n {props.children}\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n );\n});\n\nPopover.Trigger = PopoverTrigger;\nPopover.Content = PopoverContent;\n\nexport default Popover;\n"],"names":["PopoverContext","React","createContext","usePopoverContext","context","useContext","Error","Popover","children","restOptions","popover","open","_open","onOpenChange","_onOpenChange","placement","strategy","modal","offset","_offset","positionReference","hoverOptions","focusOptions","clickOptions","roleOptions","dismissOptions","uncontrolledOpen","setUncontrolledOpen","useState","data","useFloating","middleware","flip","padding","fallbackPlacements","shift","whileElementsMounted","autoUpdate","click","useClick","enabled","hover","useHover","focus","useFocus","dismiss","useDismiss","role","useRole","interactions","useInteractions","useLayoutEffect","refs","setPositionReference","current","useMemo","usePopover","Provider","value","PopoverTrigger","forwardRef","asChild","props","propRef","getReferenceProps","childrenRef","ref","useMergeRefs","setReference","isValidElement","cloneElement","jsx","onClick","PopoverContent","style","className","initialFocus","returnFocus","floatingStyles","getFloatingProps","setFloating","referenceElement","reference","theme","size","getThemeAndSize","contextElement","floatingPortalRef","useRef","useEffect","elements","domReference","closest","document","body","FloatingPortal","root","FloatingFocusManager","clsx","Trigger","Content"],"mappings":"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"}
1
+ {"version":3,"file":"Popover.js","sources":["../../../../src/components/popover/Popover.tsx"],"sourcesContent":["import {\n FloatingFocusManager,\n FloatingPortal,\n type ReferenceElement,\n type VirtualElement,\n autoUpdate,\n flip,\n offset,\n shift,\n useClick,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useInteractions,\n useMergeRefs,\n useRole,\n} from \"@floating-ui/react\";\nimport clsx from \"clsx\";\nimport * as React from \"react\";\nimport { getThemeAndSize } from \"../../utilities/getThemeAndSize.js\";\nimport type { PopoverOptions } from \"./types.js\";\n\nconst usePopover = ({\n open: _open,\n onOpenChange: _onOpenChange,\n placement = \"bottom-start\",\n strategy = \"absolute\",\n modal = true,\n offset: _offset = 4,\n positionReference,\n hoverOptions,\n focusOptions,\n clickOptions,\n roleOptions,\n dismissOptions,\n}: PopoverOptions) => {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(_open);\n\n const open = _open ?? uncontrolledOpen;\n const onOpenChange = _onOpenChange ?? setUncontrolledOpen;\n\n const data = useFloating({\n open,\n onOpenChange,\n placement,\n strategy,\n middleware: [\n offset(_offset),\n flip({ padding: 5, fallbackPlacements: [\"bottom\", \"top\"] }),\n shift({ padding: 12 }),\n ],\n whileElementsMounted: autoUpdate,\n });\n\n const context = data.context;\n\n const click = useClick(context, {\n enabled: false,\n ...clickOptions,\n });\n const hover = useHover(context, { enabled: false, ...hoverOptions });\n const focus = useFocus(context, { enabled: false, ...focusOptions });\n const dismiss = useDismiss(context, dismissOptions);\n const role = useRole(context, roleOptions);\n\n const interactions = useInteractions([click, dismiss, focus, hover, role]);\n\n React.useLayoutEffect(() => {\n if (positionReference) {\n data.refs.setPositionReference(positionReference?.current);\n }\n }, [positionReference, data.refs]);\n\n return React.useMemo(\n () => ({\n open,\n onOpenChange,\n modal,\n ...interactions,\n ...data,\n }),\n [open, onOpenChange, modal, interactions, data],\n );\n};\n\ntype PopoverContextType = ReturnType<typeof usePopover> | null;\n\nconst PopoverContext = React.createContext<PopoverContextType>(null);\n\nconst usePopoverContext = () => {\n const context = React.useContext(PopoverContext);\n\n if (context == null) {\n throw new Error(\n \"Popover komponenter må brukes innenfor en <Popover /> komponent\",\n );\n }\n\n return context;\n};\n\nexport const Popover = ({\n children,\n ...restOptions\n}: {\n children: React.ReactNode;\n} & PopoverOptions) => {\n const popover = usePopover({ ...restOptions });\n return (\n <PopoverContext.Provider value={popover}>\n {children}\n </PopoverContext.Provider>\n );\n};\n\ninterface PopoverTriggerProps {\n children: React.ReactNode;\n /**\n * Rendrer komponenten som child-elementet sitt, og slår sammen egenskaper og props.\n *\n * Default er `false`.\n *\n * @example\n * ```tsx\n * <Component asChild foo=\"bar\">\n * <Child baz=\"qux\" />\n * </Component>\n *\n * // Rendrer følgende:\n * <Child foo=\"bar\" baz=\"qux\" />\n * ```\n */\n asChild?: boolean;\n}\n\nconst PopoverTrigger = React.forwardRef<\n HTMLElement,\n React.HTMLProps<HTMLElement> & PopoverTriggerProps\n>(function PopoverTrigger({ children, asChild = false, ...props }, propRef) {\n const { refs, getReferenceProps, open, onOpenChange } = usePopoverContext();\n const childrenRef = (children as any).ref;\n const ref = useMergeRefs([refs.setReference, propRef, childrenRef]);\n\n if (asChild && React.isValidElement(children)) {\n return React.cloneElement(\n children,\n getReferenceProps({\n ref,\n ...props,\n ...children.props,\n }),\n );\n }\n\n return (\n <button\n ref={ref}\n onClick={() => onOpenChange?.(!open)}\n aria-expanded={open}\n {...getReferenceProps({\n ...props,\n className: clsx(\"jkl-popover-trigger\", props.className),\n })}\n >\n {children}\n </button>\n );\n});\n\ninterface PopoverContentProps {\n /**\n * Padding rundt innholdet i popoveren.\n *\n * Default er `0`.\n */\n padding?: 0 | 8 | 16 | 24;\n /**\n *\n * Angir hvilket element som skal motta fokus ved åpning.\n * Kan være en tabbar index eller en referanse til et element.\"\n *\n * Default er `0`, som betyr at det første fokuserbare elementet i popoveren får fokus.\n * @see https://floating-ui.com/docs/FloatingFocusManager#initialfocus\n */\n initialFocus?: number | React.RefObject<HTMLElement>;\n /**\n * Angir om fokus skal returneres til triggeren når popoveren lukkes.\n *\n * Default er `true`.\n * @see https://floating-ui.com/docs/FloatingFocusManager#returnfocus\n */\n returnFocus?: boolean;\n}\n\n// Er popover-elementet posisjonert i forhold til et annet element enn triggeren?\nconst isCustomPositioned = (\n referenceElement: ReferenceElement,\n): referenceElement is VirtualElement => {\n if (!referenceElement) return false;\n\n return \"contextElement\" in referenceElement;\n};\n\nconst PopoverContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLProps<HTMLDivElement> & PopoverContentProps\n>(function PopoverContent(\n {\n style,\n className,\n padding = 0,\n initialFocus = 0,\n returnFocus = true,\n ...props\n },\n propRef,\n) {\n const { context, modal, refs, open, floatingStyles, getFloatingProps } =\n usePopoverContext();\n const ref = useMergeRefs([refs.setFloating, propRef]);\n\n const referenceElement = refs.reference.current as ReferenceElement;\n\n const { theme, size } = isCustomPositioned(referenceElement)\n ? getThemeAndSize(referenceElement.contextElement)\n : getThemeAndSize(referenceElement);\n\n const floatingPortalRef = React.useRef<HTMLElement | null>(null);\n\n // TODO: Løser et problem hvor nestede portaler ikke \"fester\" seg til det nærmeste portal-elementet. Fjernes når alle komponenter som rendres i en portal tar i bruk popover komponenten da den håndterer dette internt. Issue: https://github.com/fremtind/jokul/issues/4356\n React.useEffect(() => {\n floatingPortalRef.current =\n context.elements.domReference?.closest<HTMLElement>(\n \"[data-portal]\",\n ) || document.body;\n }, [context.elements.domReference]);\n\n if (!open) return null;\n\n return (\n <FloatingPortal root={floatingPortalRef.current}>\n <FloatingFocusManager\n context={context}\n modal={modal}\n initialFocus={initialFocus}\n returnFocus={returnFocus}\n >\n <div\n data-theme={theme}\n data-size={size}\n className={clsx(\"jkl jkl-popover\", className)}\n ref={ref}\n style={\n {\n ...style,\n ...floatingStyles,\n \"--popover-padding\": `var(--jkl-spacing-${padding})`,\n } as React.CSSProperties\n }\n {...getFloatingProps(props)}\n >\n {props.children}\n </div>\n </FloatingFocusManager>\n </FloatingPortal>\n );\n});\n\nPopover.Trigger = PopoverTrigger;\nPopover.Content = PopoverContent;\n\nexport default Popover;\n"],"names":["PopoverContext","React","createContext","usePopoverContext","context","useContext","Error","Popover","children","restOptions","popover","open","_open","onOpenChange","_onOpenChange","placement","strategy","modal","offset","_offset","positionReference","hoverOptions","focusOptions","clickOptions","roleOptions","dismissOptions","uncontrolledOpen","setUncontrolledOpen","useState","data","useFloating","middleware","flip","padding","fallbackPlacements","shift","whileElementsMounted","autoUpdate","click","useClick","enabled","hover","useHover","focus","useFocus","dismiss","useDismiss","role","useRole","interactions","useInteractions","useLayoutEffect","refs","setPositionReference","current","useMemo","usePopover","Provider","value","PopoverTrigger","forwardRef","asChild","props","propRef","getReferenceProps","childrenRef","ref","useMergeRefs","setReference","isValidElement","cloneElement","jsx","onClick","className","clsx","PopoverContent","style","initialFocus","returnFocus","floatingStyles","getFloatingProps","setFloating","referenceElement","reference","theme","size","getThemeAndSize","contextElement","floatingPortalRef","useRef","useEffect","elements","domReference","closest","document","body","FloatingPortal","root","FloatingFocusManager","Trigger","Content"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fremtind/jokul",
3
- "version": "4.4.0",
3
+ "version": "4.5.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -10,6 +10,7 @@
10
10
  --jkl-button-padding-icon: var(--jkl-unit-20);
11
11
  --jkl-button-padding-icon-button: var(--jkl-unit-10);
12
12
  --jkl-button-tertiary-padding-icon: var(--jkl-unit-05);
13
+ --jkl-button-text-ink-offset: 0.1em;
13
14
  --jkl-icon-weight: var(--jkl-icon-weight-bold);
14
15
  --text-color: var(--jkl-color-text-default);
15
16
  --background-color: transparent;
@@ -74,8 +75,11 @@
74
75
  pointer-events: none;
75
76
  }
76
77
  .jkl-button__text {
78
+ display: block;
77
79
  width: 100%;
78
80
  max-width: 100%;
81
+ padding-block-start: var(--jkl-button-text-ink-offset);
82
+ margin-block-start: calc(var(--jkl-button-text-ink-offset) * -1);
79
83
  overflow: hidden;
80
84
  white-space: nowrap;
81
85
  text-overflow: ellipsis;