@fremtind/jokul 4.6.1 → 4.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/build-stats.html +1 -1
- package/build/cjs/components/expander/Expander.cjs +1 -1
- package/build/cjs/components/expander/Expander.cjs.map +1 -1
- package/build/cjs/components/popover/Popover.cjs +1 -1
- package/build/cjs/components/popover/Popover.cjs.map +1 -1
- package/build/cjs/components/popover/types.d.cts +8 -1
- package/build/cjs/components/select/Select.cjs +1 -1
- package/build/cjs/components/select/Select.cjs.map +1 -1
- package/build/cjs/components/system-message/types.d.cts +7 -2
- package/build/cjs/components/typography/Text.cjs +2 -0
- package/build/cjs/components/typography/Text.cjs.map +1 -0
- package/build/cjs/components/typography/Text.d.cts +5 -0
- package/build/cjs/components/typography/Title.cjs +2 -0
- package/build/cjs/components/typography/Title.cjs.map +1 -0
- package/build/cjs/components/typography/Title.d.cts +5 -0
- package/build/cjs/components/typography/index.cjs +2 -0
- package/build/cjs/components/typography/index.cjs.map +1 -0
- package/build/cjs/components/typography/index.d.cts +3 -0
- package/build/cjs/components/typography/types.cjs +2 -0
- package/build/cjs/components/typography/types.cjs.map +1 -0
- package/build/cjs/components/typography/types.d.cts +48 -0
- package/build/cjs/hooks/useListNavigation/useListNavigation.cjs +1 -1
- package/build/cjs/hooks/useListNavigation/useListNavigation.cjs.map +1 -1
- package/build/cjs/hooks/useListNavigation/useListNavigation.d.cts +11 -2
- package/build/es/components/datepicker/DatePicker.js +1 -1
- package/build/es/components/datepicker/internal/Calendar.js +1 -1
- package/build/es/components/datepicker/internal/useCalendar.js +1 -1
- package/build/es/components/datepicker/internal/utils.js +1 -1
- package/build/es/components/expander/Expander.js +1 -1
- package/build/es/components/expander/Expander.js.map +1 -1
- package/build/es/components/menu/Menu.js +1 -1
- package/build/es/components/popover/Popover.js +1 -1
- package/build/es/components/popover/Popover.js.map +1 -1
- package/build/es/components/popover/types.d.ts +8 -1
- package/build/es/components/select/Select.js +1 -1
- package/build/es/components/select/Select.js.map +1 -1
- package/build/es/components/system-message/types.d.ts +7 -2
- package/build/es/components/toast/toastContext.js +1 -1
- package/build/es/components/tooltip/Tooltip.js +1 -1
- package/build/es/components/typography/Text.d.ts +5 -0
- package/build/es/components/typography/Text.js +2 -0
- package/build/es/components/typography/Text.js.map +1 -0
- package/build/es/components/typography/Title.d.ts +5 -0
- package/build/es/components/typography/Title.js +2 -0
- package/build/es/components/typography/Title.js.map +1 -0
- package/build/es/components/typography/index.d.ts +3 -0
- package/build/es/components/typography/index.js +2 -0
- package/build/es/components/typography/index.js.map +1 -0
- package/build/es/components/typography/types.d.ts +48 -0
- package/build/es/components/typography/types.js +2 -0
- package/build/es/components/typography/types.js.map +1 -0
- package/build/es/hooks/stories/content.js +1 -1
- package/build/es/hooks/useListNavigation/useListNavigation.d.ts +11 -2
- package/build/es/hooks/useListNavigation/useListNavigation.js +1 -1
- package/build/es/hooks/useListNavigation/useListNavigation.js.map +1 -1
- package/build/es/index.js +1 -1
- package/build/es/utilities/constants/index.js +1 -1
- package/build/es/utilities/constants/unicode.js +1 -1
- package/build/es/utilities/formatters/bytes/formatBytes.js +1 -1
- package/build/es/utilities/formatters/fodselsnummer/formatFodselsnummer.js +1 -1
- package/build/es/utilities/formatters/kontonummer/formatKontonummer.js +1 -1
- package/build/es/utilities/formatters/kortnummer/formatKortnummer.js +1 -1
- package/build/es/utilities/formatters/organisasjonsnummer/formatOrganisasjonsnummer.js +1 -1
- package/build/es/utilities/formatters/telefonnummer/formatTelefonnummer.js +1 -1
- package/build/es/utilities/formatters/valuta/formatValuta.js +1 -1
- package/build/es/utilities/index.js +1 -1
- package/build/{index-CWRMnfcx.js → index-C1iqmqvT.js} +2 -2
- package/build/{index-CWRMnfcx.js.map → index-C1iqmqvT.js.map} +1 -1
- package/build/{utils-CcE6HjQp.js → utils-CtwpNW4I.js} +2 -2
- package/build/{utils-CcE6HjQp.js.map → utils-CtwpNW4I.js.map} +1 -1
- package/package.json +18 -4
- package/styles/components/countdown/countdown.css +2 -2
- package/styles/components/countdown/countdown.min.css +1 -1
- package/styles/components/expander/expandable.css +12 -10
- package/styles/components/expander/expandable.min.css +1 -1
- package/styles/components/expander/expandable.scss +15 -12
- package/styles/components/feedback/feedback.css +2 -2
- package/styles/components/feedback/feedback.min.css +1 -1
- package/styles/components/file-input/file-input.css +9 -9
- package/styles/components/file-input/file-input.min.css +1 -1
- package/styles/components/input-group/input-group.css +2 -2
- package/styles/components/input-group/input-group.min.css +1 -1
- package/styles/components/loader/loader.css +6 -6
- package/styles/components/loader/loader.min.css +1 -1
- package/styles/components/loader/skeleton-loader.css +3 -3
- package/styles/components/loader/skeleton-loader.min.css +1 -1
- package/styles/components/message/message.css +2 -2
- package/styles/components/message/message.min.css +1 -1
- package/styles/components/progress-bar/progress-bar.css +1 -1
- package/styles/components/progress-bar/progress-bar.min.css +1 -1
- package/styles/components/segmented-control/segmented-control.css +2 -2
- package/styles/components/segmented-control/segmented-control.min.css +1 -1
- package/styles/components/select/select.css +63 -14
- package/styles/components/select/select.min.css +1 -1
- package/styles/components/select/select.scss +120 -22
- package/styles/components/system-message/system-message.css +7 -16
- package/styles/components/system-message/system-message.min.css +1 -1
- package/styles/components/system-message/system-message.scss +2 -10
- package/styles/components/toast/toast.css +4 -4
- package/styles/components/toast/toast.min.css +1 -1
- package/styles/components/typography/_index.scss +2 -0
- package/styles/components/typography/text.css +52 -0
- package/styles/components/typography/text.min.css +1 -0
- package/styles/components/typography/text.scss +55 -0
- package/styles/components/typography/title.css +70 -0
- package/styles/components/typography/title.min.css +1 -0
- package/styles/components/typography/title.scss +58 -0
- package/styles/core/core.css +1 -1
- package/styles/core/core.min.css +1 -1
- package/styles/core/utility/_paragraphs.scss +11 -1
- package/styles/styles.css +220 -62
- package/styles/styles.min.css +2 -2
- package/styles/styles.scss +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useListNavigation.cjs","sources":["../../../../src/hooks/useListNavigation/useListNavigation.ts"],"sourcesContent":["import { type RefObject,
|
|
1
|
+
{"version":3,"file":"useListNavigation.cjs","sources":["../../../../src/hooks/useListNavigation/useListNavigation.ts"],"sourcesContent":["import { type RefObject, useLayoutEffect } from \"react\";\n\ntype TimerHandle = { id: number | undefined };\ntype KeyBuffer = { keys: string } | undefined;\ntype Direction = \"prev\" | \"next\" | \"first\" | \"last\";\ninterface MoveDetails {\n event: KeyboardEvent;\n list: HTMLElement;\n currentFocus: HTMLButtonElement;\n}\ninterface ListDetails {\n list: HTMLElement;\n search: KeyBuffer;\n searchResetTimer: TimerHandle;\n}\ninterface SearchDetails extends ListDetails {\n key: string;\n}\ninterface EventDetails extends ListDetails {\n event: KeyboardEvent;\n}\n/**\n * Enten `ref` eller `element` må gis. `ref` brukes når listen alltid\n * er i DOM-en; `element` foretrekkes når elementet mountes/unmountes\n * dynamisk (f.eks. portalert via floating-ui), slik at listeneren\n * re-festes når elementet faktisk er tilgjengelig.\n */\ntype UseListNavigationProps<T> =\n | {\n ref: RefObject<T | null>;\n element?: never;\n }\n | {\n ref?: never;\n element: T | null;\n };\n\nexport function useListNavigation<T extends HTMLElement>({\n ref,\n element,\n}: UseListNavigationProps<T>): void {\n // Bruker `useLayoutEffect` slik at keydown-listeneren er på plass før\n // browseren maler neste frame. Det er viktig for konsumenter som\n // flytter fokus inn i lista i en `requestAnimationFrame`-callback\n // (som Select), ellers kan første tastetrykk gå tapt.\n useLayoutEffect(() => {\n // `ref?.current` leses inne i effekten — refen er fylt i commit-\n // fasen, og var `null` i render-tid for callere som passerer\n // `ref` (som Combobox).\n const list = element ?? ref?.current ?? null;\n if (!list) return;\n\n // `TimerHandle` er et muterbart objekt slik at `resetWhenIdle`\n // kan oppdatere `id` på samme referanse — `setTimeout`-handlen må\n // være delt på tvers av tastetrykk for at `clearTimeout` skal\n // kunne avbryte forrige timeout.\n const searchResetTimer: TimerHandle = { id: undefined };\n const search: KeyBuffer = { keys: \"\" }; // keypress buffer is an object to preserve state\n const handler = (event: KeyboardEvent) => {\n handleListKeyNav({ list, event, search, searchResetTimer });\n };\n\n list.addEventListener(\"keydown\", handler);\n return () => {\n list.removeEventListener(\"keydown\", handler);\n if (searchResetTimer.id !== undefined) {\n clearTimeout(searchResetTimer.id);\n }\n };\n }, [element, ref]);\n}\n\nfunction handleMoveTo(\n direction: Direction,\n { event, list, currentFocus }: MoveDetails,\n) {\n event.preventDefault();\n moveFocusTo(direction, list, currentFocus);\n}\n\nfunction handleListKeyNav({\n list,\n event,\n search,\n searchResetTimer,\n}: EventDetails) {\n const { key, target } = event;\n const currentFocus = target as HTMLButtonElement;\n\n const moveDetails = {\n event,\n list,\n currentFocus,\n };\n\n switch (key) {\n case \"ArrowUp\":\n case \"PageUp\":\n handleMoveTo(\"prev\", moveDetails);\n break;\n case \"ArrowDown\":\n case \"PageDown\":\n handleMoveTo(\"next\", moveDetails);\n break;\n case \"Home\":\n handleMoveTo(\"first\", moveDetails);\n break;\n case \"End\":\n handleMoveTo(\"last\", moveDetails);\n break;\n case \"Tab\":\n // in a standard select, tab does nothing in-menu\n event.preventDefault();\n break;\n case \"Enter\":\n case \" \":\n break;\n\n default:\n if (search !== undefined) {\n const searchResult = findItem({\n list,\n key,\n search,\n searchResetTimer,\n });\n if (searchResult) {\n searchResult.focus();\n }\n }\n break;\n }\n}\n\nfunction moveFocusTo(\n direction: Direction,\n list: HTMLElement,\n current: HTMLButtonElement,\n) {\n const thisOption = current;\n switch (direction) {\n case \"prev\": {\n const prevOption: HTMLButtonElement | null =\n thisOption &&\n (thisOption.previousElementSibling as HTMLButtonElement);\n if (prevOption) {\n prevOption.focus();\n }\n break;\n }\n case \"next\": {\n const nextOption: HTMLButtonElement | null =\n thisOption &&\n (thisOption.nextElementSibling as HTMLButtonElement);\n if (nextOption) {\n nextOption.focus();\n }\n break;\n }\n case \"first\": {\n const firstItem =\n list.querySelector<HTMLButtonElement>(`[role=\"option\"]`);\n if (firstItem) {\n firstItem.focus();\n }\n break;\n }\n case \"last\": {\n const listItems =\n list.querySelectorAll<HTMLButtonElement>(`[role=\"option\"]`);\n if (listItems.length) {\n listItems[listItems.length - 1].focus();\n }\n break;\n }\n }\n}\n\nfunction findItem({\n list,\n key,\n search,\n searchResetTimer,\n}: SearchDetails): HTMLButtonElement | null {\n const listItems = list.querySelectorAll(`[role=\"option\"]`);\n if (!listItems.length) return null;\n\n if (search) {\n search.keys = search.keys.concat(key);\n resetWhenIdle(search, searchResetTimer);\n\n for (let n = 0; n < listItems.length; n++) {\n const label = (listItems[n] as HTMLButtonElement).innerText;\n if (label && label.toLowerCase().indexOf(search.keys) === 0) {\n return listItems[n] as HTMLButtonElement;\n }\n }\n }\n\n return null;\n}\n\nfunction resetWhenIdle(search: KeyBuffer, timer: TimerHandle) {\n if (timer.id !== undefined) {\n clearTimeout(timer.id);\n timer.id = undefined;\n }\n timer.id = window.setTimeout(() => {\n if (search) {\n search.keys = \"\";\n }\n timer.id = undefined;\n }, 500);\n}\n"],"names":["handleMoveTo","direction","event","list","currentFocus","preventDefault","current","thisOption","prevOption","previousElementSibling","focus","nextOption","nextElementSibling","firstItem","querySelector","listItems","querySelectorAll","length","moveFocusTo","ref","element","useLayoutEffect","searchResetTimer","id","search","keys","handler","key","target","moveDetails","searchResult","concat","timer","clearTimeout","window","setTimeout","resetWhenIdle","n","label","innerText","toLowerCase","indexOf","findItem","handleListKeyNav","addEventListener","removeEventListener"],"mappings":"yGAwEA,SAASA,EACLC,GACEC,MAAAA,EAAOC,KAAAA,EAAMC,aAAAA,IAEfF,EAAMG,iBA0DV,SACIJ,EACAE,EACAG,GAEA,MAAMC,EAAaD,EACnB,OAAQL,GACJ,IAAK,OAAQ,CACT,MAAMO,EACFD,GACCA,EAAWE,uBACZD,GACAA,EAAWE,QAEf,KACJ,CACA,IAAK,OAAQ,CACT,MAAMC,EACFJ,GACCA,EAAWK,mBACZD,GACAA,EAAWD,QAEf,KACJ,CACA,IAAK,QAAS,CACV,MAAMG,EACFV,EAAKW,cAAiC,mBACtCD,GACAA,EAAUH,QAEd,KACJ,CACA,IAAK,OAAQ,CACT,MAAMK,EACFZ,EAAKa,iBAAoC,mBACzCD,EAAUE,QACVF,EAAUA,EAAUE,OAAS,GAAGP,QAEpC,KACJ,EAER,CAnGIQ,CAAYjB,EAAWE,EAAMC,EACjC,2BAzCO,UACHe,IAAAA,EACAC,QAAAA,IAMAC,EAAAA,gBAAgB,KAIZ,MAAMlB,EAAOiB,GAAWD,GAAKb,SAAW,KACxC,IAAKH,EAAM,OAMX,MAAMmB,EAAgC,CAAEC,QAAI,GACtCC,EAAoB,CAAEC,KAAM,IAC5BC,EAAWxB,KAsBzB,UACIC,KAAAA,EACAD,MAAAA,EACAsB,OAAAA,EACAF,iBAAAA,IAEA,MAAQK,IAAAA,EAAKC,OAAAA,GAAW1B,EAGlB2B,EAAc,CAChB3B,MAAAA,EACAC,KAAAA,EACAC,aALiBwB,GAQrB,OAAQD,GACJ,IAAK,UACL,IAAK,SACD3B,EAAa,OAAQ6B,GACrB,MACJ,IAAK,YACL,IAAK,WACD7B,EAAa,OAAQ6B,GACrB,MACJ,IAAK,OACD7B,EAAa,QAAS6B,GACtB,MACJ,IAAK,MACD7B,EAAa,OAAQ6B,GACrB,MACJ,IAAK,MAED3B,EAAMG,iBACN,MACJ,IAAK,QACL,IAAK,IACD,MAEJ,QACI,QAAe,IAAXmB,EAAsB,CACtB,MAAMM,EA0DtB,UACI3B,KAAAA,EACAwB,IAAAA,EACAH,OAAAA,EACAF,iBAAAA,IAEA,MAAMP,EAAYZ,EAAKa,iBAAiB,mBACxC,IAAKD,EAAUE,OAAQ,OAAO,KAE9B,GAAIO,EAAQ,CACRA,EAAOC,KAAOD,EAAOC,KAAKM,OAAOJ,GAczC,SAAuBH,EAAmBQ,QACrB,IAAbA,EAAMT,KACNU,aAAaD,EAAMT,IACnBS,EAAMT,QAAK,GAEfS,EAAMT,GAAKW,OAAOC,WAAW,KACrBX,IACAA,EAAOC,KAAO,IAElBO,EAAMT,QAAK,GACZ,IACP,CAxBQa,CAAcZ,EAAQF,GAEtB,IAAA,IAASe,EAAI,EAAGA,EAAItB,EAAUE,OAAQoB,IAAK,CACvC,MAAMC,EAASvB,EAAUsB,GAAyBE,UAClD,GAAID,GAAsD,IAA7CA,EAAME,cAAcC,QAAQjB,EAAOC,MAC5C,OAAOV,EAAUsB,EAEzB,CACJ,CAEA,OAAO,IACX,CAhFqCK,CAAS,CAC1BvC,KAAAA,EACAwB,IAAAA,EACAH,OAAAA,EACAF,iBAAAA,IAEAQ,GACAA,EAAapB,OAErB,EAGZ,CAzEYiC,CAAiB,CAAExC,KAAAA,EAAMD,MAAAA,EAAOsB,OAAAA,EAAQF,iBAAAA,KAG5C,OAAAnB,EAAKyC,iBAAiB,UAAWlB,GAC1B,KACHvB,EAAK0C,oBAAoB,UAAWnB,QACR,IAAxBJ,EAAiBC,IACjBU,aAAaX,EAAiBC,MAGvC,CAACH,EAASD,GACjB"}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Enten `ref` eller `element` må gis. `ref` brukes når listen alltid
|
|
4
|
+
* er i DOM-en; `element` foretrekkes når elementet mountes/unmountes
|
|
5
|
+
* dynamisk (f.eks. portalert via floating-ui), slik at listeneren
|
|
6
|
+
* re-festes når elementet faktisk er tilgjengelig.
|
|
7
|
+
*/
|
|
2
8
|
type UseListNavigationProps<T> = {
|
|
3
|
-
/** Ref til et element med rollen `listbox` */
|
|
4
9
|
ref: RefObject<T | null>;
|
|
10
|
+
element?: never;
|
|
11
|
+
} | {
|
|
12
|
+
ref?: never;
|
|
13
|
+
element: T | null;
|
|
5
14
|
};
|
|
6
|
-
export declare function useListNavigation<T extends HTMLElement>({ ref, }: UseListNavigationProps<T>): void;
|
|
15
|
+
export declare function useListNavigation<T extends HTMLElement>({ ref, element, }: UseListNavigationProps<T>): void;
|
|
7
16
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{c as r}from"../../../clsx-BeLtu-UY.js";import{d as a,g as o}from"../../../utils-
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{c as r}from"../../../clsx-BeLtu-UY.js";import{d as a,g as o}from"../../../utils-CtwpNW4I.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 c}from"../../utilities/formatters/date/formatDate.js";import{IconButton as d}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),re=te?a(te).startOf("day").toDate():void 0,ae=h(B),oe=ae?a(ae).startOf("day").toDate():void 0,[ne,le]=l(o(P,I,re,oe)),[se,ie]=l(null),[ue,ce]=l(O),de=s(null),pe=s(null),me=s(null),fe=s(null),ve=s(!1),De=i(e=>{fe.current=e,j&&("function"==typeof j?j(e):j.current=e)},[j]),he=i(e=>{M&&pe.current&&(pe.current.contains(e.relatedTarget)||M(e,ne,{error:se,value:e.target.value}))},[M,ne,se]),be=i(e=>{H&&H(e,ne,{error:se,value:e.target.value})},[H,ne,se]),ge=i(e=>{"Escape"===e.key&&(ce(!1),e.preventDefault(),e.stopPropagation()),$?.onKeyDown&&$.onKeyDown(e)},[$]),ke=i(e=>{const t=e.currentTarget.value,r=((e,t)=>{const r=e.replace(/\D/g,""),a=c(r,{partial:!0}),o=e.replace(/\D+$/,""),n=8===r.length?c(r):e,l=h(n)?n:null,s=t&&e!==r&&o===a&&void 0===h(e)&&null===l;return l??(s?r:e)})(t,ve.current);r!==t&&((e,t)=>{const r=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"value")?.set;r?r.call(e,t):e.value=t})(e.currentTarget,r);const a=t.replace(/\D/g,"");ve.current=t===a&&r===c(a)&&r!==t&&void 0!==h(r);const{date:o,error:n}=(({value:e,minDate:t,maxDate:r})=>{if(!e)return{date:null,error:null};const a=h(e);return a?t&&!g(a,t)?{date:a,error:"OUTSIDE_LOWER_BOUND"}:r&&!k(a,r)?{date:a,error:"OUTSIDE_UPPER_BOUND"}:{date:a,error:null}:{date:null,error:"WRONG_FORMAT"}})({value:r,minDate:re,maxDate:oe});o&&!n&&ce(!1),ie(n),le(o),G&&G(e,o,{error:n,value:r})},[G,re,oe]),je=i(e=>{u(()=>{ce(!ue)});const t=de.current,r=t&&t.querySelector('[aria-pressed="true"]');window.requestAnimationFrame(()=>r?.focus()),$?.onClick&&$.onClick(e)},[ue,$]),ye=i(({date:e})=>{if(ce(!1),le(e),fe.current){const t=fe.current;ve.current=!1,t.value=b(e);const r=document.createEvent("HTMLEvents");r.initEvent("input",!0,!1),t.dispatchEvent(r),t.focus(),G&&G(r,e,{error:null,value:t.value})}},[G]),Le=i(e=>{e.preventDefault(),ce(!1),me.current?.focus()},[]);return e(m,{id:L,className:r("jkl-datepicker",w),...ee,ref:pe,label:x,labelProps:C,helpLabel:S,errorLabel:N,supportLabelProps:Q,tooltip:X,description:Z,render:r=>e(v,{"data-focused":ue?"true":void 0,ref:De,"data-testid":"jkl-datepicker__input","data-testautoid":y,className:"jkl-datepicker__input",name:_,defaultValue:I,value:P,type:"text",placeholder:W,width:A,onFocus:he,onBlur:be,onChange:ke,actionButton:t(f,{positionReference:fe,open:ue,onOpenChange:()=>ce(!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:je,onKeyDown:ge,asChild:!0,children:e(d,{children:e(p,{})})}),e(f.Content,{initialFocus:-1,padding:24,children:e(D,{ref:de,date:ne,minDate:re,maxDate:oe,days:U,months:V,monthLabel:F,yearLabel:K,yearsToShow:E,onDateSelected:ye,onTabOutside:Le})})]}),...Y,...r,"aria-invalid":R||!!N})})});j.displayName="DatePicker";export{j as DatePicker};
|
|
2
2
|
//# sourceMappingURL=DatePicker.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{forwardRef as a,useReducer as n,useEffect as r,useCallback as l,useRef as o}from"react";import{flushSync as s}from"react-dom";import{useId as d}from"../../../hooks/useId/useId.js";import{Button as c}from"../../button/Button.js";import{ArrowLeftIcon as i}from"../../icon/icons/ArrowLeftIcon.js";import{ArrowRightIcon as u}from"../../icon/icons/ArrowRightIcon.js";import{ChevronDownIcon as h}from"../../icon/icons/ChevronDownIcon.js";import{calendarReducer as m,calendarInitializer as f}from"./calendarReducer.js";import{useCalendar as g}from"./useCalendar.js";import{D as b,a as p,i as v,s as k,b as j,c as D,e as w,f as y}from"../../../../utils-
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import{forwardRef as a,useReducer as n,useEffect as r,useCallback as l,useRef as o}from"react";import{flushSync as s}from"react-dom";import{useId as d}from"../../../hooks/useId/useId.js";import{Button as c}from"../../button/Button.js";import{ArrowLeftIcon as i}from"../../icon/icons/ArrowLeftIcon.js";import{ArrowRightIcon as u}from"../../icon/icons/ArrowRightIcon.js";import{ChevronDownIcon as h}from"../../icon/icons/ChevronDownIcon.js";import{calendarReducer as m,calendarInitializer as f}from"./calendarReducer.js";import{useCalendar as g}from"./useCalendar.js";import{D as b,a as p,i as v,s as k,b as j,c as D,e as w,f as y}from"../../../../utils-CtwpNW4I.js";const M=["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],F=["man","tir","ons","tor","fre","lør","søn"],S=a((a,S)=>{const{date:A,defaultSelected:N,minDate:_,maxDate:$,days:x=F,months:C=M,monthLabel:E="Velg måned",yearLabel:Y="Velg år",yearsToShow:I=b,onTabOutside:O,...T}=a,R=d("jkl-calendar"),[{offset:L,selectedDate:q,shownDate:K},B]=n(m,p(A,N,_,$),f),J=K.getMonth(),P=K.getFullYear();r(()=>{B({type:"SET_SELECTED_DATE",newDate:p(A,N,_,$)})},[A,N,_,$]);const V=l(e=>{B({type:"SET_OFFSET",newOffset:e})},[]),{calendars:z,getBackProps:U,getDateProps:W,getForwardProps:G,handleOffsetChanged:H}=g({date:q,selected:q,minDate:_,maxDate:$,offset:L,onOffsetChanged:V,firstDayOfWeek:1,...T}),Q=o(null),X=l(e=>{if(!Q.current)return;const t=document.activeElement,a=Q.current.querySelectorAll('button.jkl-calendar-date-button:not([data-adjacent="true"]'),n=async e=>{t?.setAttribute("tabindex","-1"),e.setAttribute("tabindex","0"),e.focus()};a.forEach((r,l)=>{const o=l+e;if(r===t)if(o<=a.length-1&&o>=0)n(a[o]);else if(e<0){if(v({calendars:z,minDate:_})||(s(()=>{H(L-k({calendars:z,offset:1,minDate:_}))}),!Q.current))return;const e=Q.current.querySelectorAll('button.jkl-calendar-date-button:not([data-adjacent="true"]');e[e.length+o]&&(e[0].setAttribute("tabindex","-1"),n(e[e.length+o]))}else{if(j({calendars:z,maxDate:$})||(s(()=>{H(L+D({calendars:z,offset:1,maxDate:$}))}),!Q.current))return;const e=Q.current.querySelectorAll('button.jkl-calendar-date-button:not([data-adjacent="true"]');e[o-a.length]&&(e[0].setAttribute("tabindex","-1"),n(e[o-a.length]))}})},[H,L,z,$,_]),Z=l(e=>{switch(e.key){case"ArrowUp":X(-7),e.preventDefault();break;case"ArrowRight":X(1),e.preventDefault();break;case"ArrowDown":X(7),e.preventDefault();break;case"ArrowLeft":X(-1),e.preventDefault()}},[X]),ee=l(e=>{if("Tab"!==e.key)return;const t=Q.current?.querySelectorAll('button:not([disabled]):not([tabindex="-1"]), select');if(!t)return;const a=t[0],n=t[t.length-1];e.shiftKey||document.activeElement!==n?e.shiftKey&&document.activeElement===a&&(n.focus(),e.preventDefault()):(a.focus(),e.preventDefault())},[]),te=l(e=>{const{date:t,selected:a,selectable:n,prevMonth:r,nextMonth:l}=e;return!!n&&!(!a&&t.toString()!==_?.toString()&&(r||l||K.getFullYear()!==t.getFullYear()||q.getMonth()===t.getMonth()||1!==t.getDate()))},[K,_,q]),ae=l(()=>{_&&K.getFullYear()-_.getFullYear()===0&&K.getMonth()-_.getMonth()===1?document.querySelector(`[data-testid="${R}-forward-button"]`)?.focus():$&&$.getFullYear()-K.getFullYear()===0&&$.getMonth()-K.getMonth()===1&&document.querySelector(`[data-testid="${R}-back-button"]`)?.focus()},[_,$,K,R]),ne=l(e=>{if(4!==e.target.value.length)return;const t=Number.parseInt(e.target.value);if(Number.isNaN(t))return;let a=12*(t-K.getFullYear());const n=new Date(K.getFullYear(),K.getMonth()+a,K.getDate());$&&$.getFullYear()===n.getFullYear()&&$.getMonth()<n.getMonth()?a-=n.getMonth()-$.getMonth():_&&_.getFullYear()===n.getFullYear()&&_.getMonth()>n.getMonth()&&(a+=_.getMonth()-n.getMonth()),B({type:"ADD_OFFSET",addedOffset:a})},[K,_,$]),re=l(e=>{if(!q&&!A)return;const t=K.getFullYear()-(q||new Date).getFullYear(),a=Number.parseInt(e.target.value)-(q||new Date).getMonth();B({type:"SET_OFFSET",newOffset:12*t+a})},[q,A,K]),le=w(P,_,$,I),oe=y(P,C,_,$);return e("div",{ref:S,id:R,className:"jkl-calendar","data-testid":"jkl-calendar",children:t("div",{className:"jkl-calendar__padding",ref:Q,onKeyDown:ee,children:[t("fieldset",{className:"jkl-calendar-navigation",children:[t("div",{children:[e(c,{...U({calendars:z,onClick:ae}),"data-testid":`${R}-back-button`,variant:"ghost",icon:e(i,{variant:"medium",bold:!0})}),e(c,{...G({calendars:z,onClick:ae}),variant:"ghost","data-testid":`${R}-forward-button`,icon:e(u,{variant:"medium",bold:!0})})]}),t("div",{children:[t("div",{className:"jkl-calendar-navigation-dropdown",children:[e("select",{onChange:re,className:"jkl-calendar-navigation-dropdown__select","aria-label":E,value:J.toString(),children:oe.map(({label:t,value:a})=>e("option",{value:a,children:t},a))}),e(h,{bold:!0,className:"jkl-calendar-navigation-dropdown__chevron"})]}),t("div",{className:"jkl-calendar-navigation-dropdown",children:[e("select",{onChange:ne,className:"jkl-calendar-navigation-dropdown__select","aria-label":Y,value:P.toString(),children:le.map(t=>e("option",{value:t,children:t},t))}),e(h,{bold:!0,className:"jkl-calendar-navigation-dropdown__chevron"})]})]})]}),z.map(a=>t("table",{className:"jkl-calendar-table","data-testid":"jkl-datepicker-calendar",children:[t("caption",{className:"jkl-sr-only",children:[C[a.month],", ",a.year]}),e("thead",{children:e("tr",{children:x.map(t=>e("th",{children:t},`${a.month}${a.year}${t}`))})}),e("tbody",{"data-testid":"jkl-datepicker-dates",children:a.weeks.map((t,n)=>e("tr",{children:t.map((t,r)=>{const l=`${a.month}${a.year}${n}${r}`;if("string"==typeof t)return e("td",{className:"jkl-calendar__date jkl-calendar__date--empty",children:t},l);const{date:o,selectable:s,today:d,prevMonth:c,nextMonth:i}=t;return e("td",{children:e("button",{...W({dateObj:t}),type:"button",className:"jkl-calendar-date-button",tabIndex:te(t)?0:-1,"aria-label":`${o.getDate()}. ${C[o.getMonth()].toLowerCase()}`,"aria-current":d?"date":void 0,"data-adjacent":c||i?"true":void 0,disabled:!s,onKeyDown:Z,children:e("span",{"aria-hidden":"true",children:o.getDate()})})},l)})},`${a.month}${a.year}${n}`))})]},`${a.month}${a.year}`))]})})});S.displayName="Calendar";export{S as Calendar};
|
|
2
2
|
//# sourceMappingURL=Calendar.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{h as e,d as a,b as t,j as n,i as s,s as o,c as f}from"../../../../utils-
|
|
1
|
+
import{h as e,d as a,b as t,j as n,i as s,s as o,c as f}from"../../../../utils-CtwpNW4I.js";import{useState as l}from"react";function d(e){return void 0!==e}function i(e,{onClick:a,dateObj:t}){return{onClick:n(a,a=>{e(t,a)}),disabled:!t.selectable,"aria-pressed":t.selected,role:"button"}}function r({minDate:e,offsetMonth:a,handleOffsetChanged:t},{onClick:f,offset:l=1,calendars:d}){const i=`Gå tilbake ${l} måned${1===l?"":"er"}`;return{onClick:n(f,()=>{t(a-o({calendars:d,offset:l,minDate:e}))}),disabled:s({calendars:d,minDate:e}),"aria-label":i,title:i}}function c({maxDate:e,offsetMonth:a,handleOffsetChanged:s},{onClick:o,offset:l=1,calendars:d}){const i=`Gå frem ${l} måned${1===l?"":"er"}`;return{onClick:n(o,()=>{s(a+f({calendars:d,offset:l,maxDate:e}))}),disabled:t({calendars:d,maxDate:e}),"aria-label":i,title:i}}function u({date:t=a().startOf("day").toDate(),maxDate:n,minDate:s,monthsToDisplay:o=1,firstDayOfWeek:f=0,showOutsideDays:u=!0,offset:m,onDateSelected:D,onOffsetChanged:h,selected:b}){const[C,O]=l(0),k=function(e,a){return d(e)?e:a}(m,C);function g(e){d(m)||O(e),h(e)}return{calendars:e({date:t,selected:b,monthsToDisplay:o,minDate:s,maxDate:n,offset:k,firstDayOfWeek:f,showOutsideDays:u}),getDateProps:i.bind(null,D),getBackProps:r.bind(null,{minDate:s,offsetMonth:k,handleOffsetChanged:g}),getForwardProps:c.bind(null,{maxDate:n,offsetMonth:k,handleOffsetChanged:g}),handleOffsetChanged:g}}export{u as useCalendar};
|
|
2
2
|
//# sourceMappingURL=useCalendar.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{D as a,c as s,j as t,
|
|
1
|
+
import{D as a,c as s,j as t,k as e,l as i,h as o,g as n,a as r,f as d,e as l,i as c,b as g,m,s as p}from"../../../../utils-CtwpNW4I.js";import"react";import"../utils.js";export{a as DEFAULT_YEARS_TO_SHOW,s as addMonth,t as composeEventHandlers,e as dateHasChanged,i as dateIsOutsideRange,o as getCalendars,n as getInitialDate,r as getInitialDateShown,d as getMonthSelectOptions,l as getYearSelectOptions,c as isBackDisabled,g as isForwardDisabled,m as isSameDay,p as subtractMonth};
|
|
2
2
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as o,jsx as n}from"react/jsx-runtime";import{c}from"../../../clsx-BeLtu-UY.js";import
|
|
1
|
+
import{jsxs as o,jsx as n}from"react/jsx-runtime";import{c as i}from"../../../clsx-BeLtu-UY.js";import c,{useContext as s,useRef as r,useImperativeHandle as e,useEffect as t}from"react";import{ChevronDownIcon as p}from"../icon/icons/ChevronDownIcon.js";import"../icon/Icon.js";import"../icon/icons/animated/ArrowVerticalAnimated.js";import"../icon/icons/animated/ArrowHorizontalAnimated.js";import"../icon/icons/animated/PlusRemoveAnimated.js";import"../icon/icons/ArrowDownIcon.js";import"../icon/icons/ArrowLeftIcon.js";import"../icon/icons/ArrowNorthEastIcon.js";import"../icon/icons/ArrowRightIcon.js";import"../icon/icons/ArrowUpIcon.js";import"../icon/icons/CalendarIcon.js";import"../icon/icons/CheckIcon.js";import"../icon/icons/ChevronLeftIcon.js";import"../icon/icons/ChevronRightIcon.js";import{ChevronUpIcon as m}from"../icon/icons/ChevronUpIcon.js";import"../icon/icons/CloseIcon.js";import"../icon/icons/CopyIcon.js";import"../icon/icons/DotsIcon.js";import"../icon/icons/DragIcon.js";import"../icon/icons/ErrorIcon.js";import"../icon/icons/GreenCheckIcon.js";import"../icon/icons/HamburgerIcon.js";import"../icon/icons/InfoIcon.js";import"../icon/icons/LinkIcon.js";import"../icon/icons/MinusIcon.js";import"../icon/icons/OpenInNewIcon.js";import"../icon/icons/PenIcon.js";import"../icon/icons/PlusIcon.js";import"../icon/icons/QuestionIcon.js";import"../icon/icons/RedCrossIcon.js";import"../icon/icons/SearchIcon.js";import"../icon/icons/SuccessIcon.js";import"../icon/icons/ThumbDownIcon.js";import"../icon/icons/ThumbUpIcon.js";import"../icon/icons/TrashCanIcon.js";import"../icon/icons/WarningIcon.js";import{ExpanderContext as a}from"./context.js";const j=c.forwardRef(function(c,j){const{children:I,as:l="summary",open:u,icon:d,className:f,onClick:h,expandDirection:x,...C}=c,w=l,{open:v,onToggle:b,setExpanderHeight:A}=s(a),g=r();e(j,()=>g.current,[]);const k="boolean"==typeof u,D=k?u:v,E="up"===x?m:p;return t(()=>{if(k)return;const o=new ResizeObserver(()=>{A(g.current?.offsetHeight||64)});return g.current?(o.observe(g.current),()=>o.disconnect()):()=>{}},[k,A]),o(w,{ref:g,className:i("jkl-expander",{"jkl-expander--open":D},f),..."button"===l?{type:C.type||"button"}:{},onClick:o=>{o.preventDefault(),k||b(),h?.(o)},...C,children:[d||null,n("span",{className:"jkl-expander__label",children:I}),n(E,{className:"jkl-expander__chevron"})]})});j.displayName="ExpandablePanel.Header";export{j as Expander};
|
|
2
2
|
//# sourceMappingURL=Expander.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Expander.js","sources":["../../../../src/components/expander/Expander.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, {\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n} from \"react\";\nimport type { PolymorphicRef } from \"../../utilities/polymorphism/polymorphism.js\";\nimport { ChevronDownIcon } from \"../icon/icons/ChevronDownIcon.js\";\nimport { ChevronUpIcon } from \"../icon/index.js\";\nimport { ExpanderContext } from \"./context.js\";\nimport type {\n ExpandableContext,\n ExpanderComponent,\n ExpanderProps,\n} from \"./types.js\";\n\nexport const Expander = React.forwardRef(function Expander<\n ElementType extends React.ElementType = \"summary\",\n>(props: ExpanderProps<ElementType>, ref?: PolymorphicRef<ElementType>) {\n const {\n children,\n as = \"summary\",\n open: controlledOpen,\n icon,\n className,\n onClick,\n expandDirection,\n ...rest\n } = props;\n const El = as;\n\n const {\n open: contextOpen,\n onToggle,\n setExpanderHeight,\n } = useContext<ExpandableContext>(ExpanderContext);\n\n const internalRef = useRef<HTMLElement>();\n useImperativeHandle(ref, () => internalRef.current, []);\n\n const isOpen = controlledOpen
|
|
1
|
+
{"version":3,"file":"Expander.js","sources":["../../../../src/components/expander/Expander.tsx"],"sourcesContent":["import clsx from \"clsx\";\nimport React, {\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n} from \"react\";\nimport type { PolymorphicRef } from \"../../utilities/polymorphism/polymorphism.js\";\nimport { ChevronDownIcon } from \"../icon/icons/ChevronDownIcon.js\";\nimport { ChevronUpIcon } from \"../icon/index.js\";\nimport { ExpanderContext } from \"./context.js\";\nimport type {\n ExpandableContext,\n ExpanderComponent,\n ExpanderProps,\n} from \"./types.js\";\n\nexport const Expander = React.forwardRef(function Expander<\n ElementType extends React.ElementType = \"summary\",\n>(props: ExpanderProps<ElementType>, ref?: PolymorphicRef<ElementType>) {\n const {\n children,\n as = \"summary\",\n open: controlledOpen,\n icon,\n className,\n onClick,\n expandDirection,\n ...rest\n } = props;\n const El = as;\n\n const {\n open: contextOpen,\n onToggle,\n setExpanderHeight,\n } = useContext<ExpandableContext>(ExpanderContext);\n\n const internalRef = useRef<HTMLElement>();\n useImperativeHandle(ref, () => internalRef.current, []);\n\n // Når `open`-propen er satt eier konsumenten state-en og Expander er\n // kontrollert. Da skal vi ikke arve verken visning eller toggle-callback\n // fra et omkringliggende ExpandablePanel — ellers ville klikk på en\n // nestet Expander også togglet panelet.\n const isControlled = typeof controlledOpen === \"boolean\";\n const isOpen = isControlled ? controlledOpen : contextOpen;\n\n const Chevron = expandDirection === \"up\" ? ChevronUpIcon : ChevronDownIcon;\n\n useEffect(() => {\n // Kontrollert Expander skal være helt isolert fra et eventuelt\n // omkringliggende ExpandablePanel — hverken state, klikk eller\n // høyde-rapportering skal arve oppover. Hopp over måling slik at\n // panel-headerens fokuscontainer ikke får raden sin høyde.\n if (isControlled) return;\n\n const observer = new ResizeObserver(() => {\n // Default to 64 if the height can not be read because that is\n // the height of the default summary element. In a custom component\n // this means that the focus ring might be slightly misaligned but\n // in most cases we will be able to read the ref correctly.\n setExpanderHeight(internalRef.current?.offsetHeight || 64);\n });\n if (internalRef.current) {\n observer.observe(internalRef.current);\n return () => observer.disconnect();\n }\n return () => {};\n }, [isControlled, setExpanderHeight]);\n\n return (\n <El\n ref={internalRef}\n className={clsx(\n \"jkl-expander\",\n {\n \"jkl-expander--open\": isOpen,\n },\n className,\n )}\n // If the consumer uses the Expander as a button but does not\n // supply a type, then we set type to \"button\"\n {...(as === \"button\" ? { type: rest.type || \"button\" } : {})}\n onClick={(e) => {\n e.preventDefault();\n if (!isControlled) {\n onToggle();\n }\n onClick?.(e);\n }}\n {...rest}\n >\n {icon || null}\n <span className=\"jkl-expander__label\">{children}</span>\n <Chevron className=\"jkl-expander__chevron\" />\n </El>\n );\n}) as ExpanderComponent;\n\nExpander.displayName = \"ExpandablePanel.Header\";\n"],"names":["Expander","React","forwardRef","props","ref","children","as","open","controlledOpen","icon","className","onClick","expandDirection","rest","El","contextOpen","onToggle","setExpanderHeight","useContext","ExpanderContext","internalRef","useRef","useImperativeHandle","current","isControlled","isOpen","Chevron","ChevronUpIcon","ChevronDownIcon","useEffect","observer","ResizeObserver","offsetHeight","observe","disconnect","jsxs","clsx","type","e","preventDefault","jsx","displayName"],"mappings":"qoDAiBO,MAAMA,EAAWC,EAAMC,WAAW,SAEvCC,EAAmCC,GACjC,MACIC,SAAAA,EACAC,GAAAA,EAAK,UACLC,KAAMC,EACNC,KAAAA,EACAC,UAAAA,EACAC,QAAAA,EACAC,gBAAAA,KACGC,GACHV,EACEW,EAAKR,GAGPC,KAAMQ,EACNC,SAAAA,EACAC,kBAAAA,GACAC,EAA8BC,GAE5BC,EAAcC,IACpBC,EAAoBlB,EAAK,IAAMgB,EAAYG,QAAS,IAMpD,MAAMC,EAAyC,kBAAnBhB,EACtBiB,EAASD,EAAehB,EAAiBO,EAEzCW,EAA8B,OAApBd,EAA2Be,EAAgBC,EAE3D,OAAAC,EAAU,KAKN,GAAIL,EAAc,OAElB,MAAMM,EAAW,IAAIC,eAAe,KAKhCd,EAAkBG,EAAYG,SAASS,cAAgB,MAE3D,OAAIZ,EAAYG,SACZO,EAASG,QAAQb,EAAYG,SACtB,IAAMO,EAASI,cAEnB,QACR,CAACV,EAAcP,IAGdkB,EAACrB,EAAA,CACGV,IAAKgB,EACLV,UAAW0B,EACP,eACA,CACI,qBAAsBX,GAE1Bf,MAIQ,WAAPJ,EAAkB,CAAE+B,KAAMxB,EAAKwB,MAAQ,UAAa,CAAA,EACzD1B,QAAU2B,IACNA,EAAEC,iBACGf,GACDR,IAEJL,IAAU2B,OAEVzB,EAEHR,SAAA,CAAAI,GAAQ,KACT+B,EAAC,OAAA,CAAK9B,UAAU,sBAAuBL,SAAAA,IACvCmC,EAACd,EAAA,CAAQhB,UAAU,4BAG/B,GAEAV,EAASyC,YAAc"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as e,jsx as s}from"react/jsx-runtime";import{useFloatingTree as t,useFloatingNodeId as n,useFloatingParentNodeId as o,useFloating as a,autoUpdate as r,offset as i,flip as l,shift as u,useInteractions as d,useHover as c,
|
|
1
|
+
import{jsxs as e,jsx as s}from"react/jsx-runtime";import{useFloatingTree as t,useFloatingNodeId as n,useFloatingParentNodeId as o,useFloating as a,autoUpdate as r,offset as i,flip as l,shift as u,useInteractions as d,useHover as c,safePolygon as m,useClick as p,useDismiss as f,useRole as g,useListNavigation as h,useMergeRefs as v,useTransitionStyles as k,FloatingNode as x,FloatingPortal as y,FloatingFocusManager as P,FloatingTree as j}from"@floating-ui/react";import{c as F}from"../../../clsx-BeLtu-UY.js";import w,{forwardRef as I,useId as M,useRef as C,useState as E,useEffect as S}from"react";import{useBrowserPreferences as N}from"../../hooks/useBrowserPreferences/useBrowserPreferences.js";import"../../hooks/useScreen/useScreen.js";import"../../hooks/useId/useId.js";import{getThemeAndSize as O}from"../../utilities/getThemeAndSize.js";import{SlotComponent as R}from"../../utilities/polymorphism/SlotComponent.js";import{useMenuWideEvents as b}from"./useMenuWideEvents.js";function T(e,s=0){switch(e){case"top":default:return`0 ${s}px`;case"left":return`${s}px 0`;case"bottom":return`0 ${-s}px`;case"right":return-s+"px 0"}}const z=I((j,I)=>{const{children:z,className:A,initialPlacement:D,openOnHover:$=!1,keepOpenOnClickOutside:B=!1,triggerElement:H,isOpen:K,onToggle:V,...W}=j,q=`"jkl-menu"${M()}`,{prefersReducedMotion:L}=N(),U=t(),G=n(),J=o(),Q=null!=J,X=C([]),[Y,Z]=E(null),{allowHover:_,isOpen:ee,setIsOpen:se}=b(U,G,J),te=void 0!==K?K:ee;S(()=>V?.(te),[te,V]);const{refs:ne,placement:oe,context:ae,floatingStyles:re}=a({nodeId:G,open:te,onOpenChange:se,placement:D||(Q?"right-start":"bottom-start"),middleware:[i(2),l({fallbackAxisSideDirection:"end",crossAxis:!1}),u({padding:8})],whileElementsMounted:r}),{getReferenceProps:ie,getFloatingProps:le,getItemProps:ue}=d([c(ae,{enabled:$&&_,delay:{open:75},handleClose:m({requireIntent:!0,blockPointerEvents:!0})}),p(ae,{event:"mousedown"}),f(ae,{outsidePress:!B}),g(ae,{role:"menu"}),h(ae,{listRef:X,activeIndex:Y,nested:Q,onNavigate:Z})]),de=v([ne.setReference,I]),{theme:ce,size:me}=O(ne.reference.current),{isMounted:pe,styles:fe}=k(ae,{duration:{open:L?0:250,close:L?0:150},initial:({side:e})=>({opacity:0,translate:T(e,5)}),open:({side:e})=>({opacity:1,translate:T(e,0)}),close:({side:e})=>({opacity:0,translate:T(e,5)})});return e(x,{id:G,children:[w.isValidElement(H)&&s(R,{...ie({...W,ref:de,role:Q?"menuitem":void 0,"aria-controls":q,onClick(e){e.stopPropagation()}}),children:H}),pe&&s(y,{children:s(P,{context:ae,modal:!1,initialFocus:Q?-1:0,returnFocus:!Q,children:s("div",{className:F("jkl jkl-menu",A),"data-theme":ce,"data-size":me,role:"menu","data-placement":oe,"aria-live":"assertive","aria-hidden":!te,ref:ne.setFloating,...le({id:q,style:{...re,...fe}}),children:w.Children.map(z,(e,t)=>w.isValidElement(e)?s(R,{...ue({...e.props,tabIndex:Y===t?0:-1,role:"menuitem",ref(e){X.current[t]=e},onClick(e){e.defaultPrevented||U?.events.emit("click")},onKeyDown(s){e.props.onKeyDown?.(s),!s.defaultPrevented&&(U?.events.emit("keydown"),"menuitemcheckbox"===s.currentTarget.role&&"Enter"===s.key&&se(!1))},onMouseEnter(){_&&te&&Z(t)}}),children:e}):e)})})})]})});z.displayName="MenuComponent";const A=I((e,t)=>null===o()?s(j,{children:s(z,{ref:t,...e})}):s(z,{ref:t,...e}));A.displayName="Menu";export{A as Menu};
|
|
2
2
|
//# sourceMappingURL=Menu.js.map
|
|
@@ -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 p,useDismiss as d,useRole as
|
|
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 m,useInteractions as f}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 b=h.createContext(null),x=()=>{const e=h.useContext(b);if(null==e)throw new Error("Popover komponenter må brukes innenfor en <Popover /> komponent");return e},k=({children:t,...n})=>{const o=(({open:e,onOpenChange:t,placement:n="bottom-start",strategy:o="absolute",modal:g=!0,offset:v=4,positionReference:b,onPlacementChange:x,hoverOptions:k,focusOptions:C,clickOptions:F,roleOptions:P,dismissOptions:R})=>{const[y,E]=h.useState(e),O=e??y,j=t??E,w=s({open:O,onOpenChange:j,placement:n,strategy:o,middleware:[a(v),i({padding:5,fallbackPlacements:["bottom","top"]}),l({padding:12})],whileElementsMounted:r}),z=w.context,M=c(z,{enabled:!1,...F}),N=u(z,{enabled:!1,...k}),S=p(z,{enabled:!1,...C}),T=d(z,R),A=m(z,P),L=f([M,T,S,N,A]);return h.useLayoutEffect(()=>{b&&w.refs.setPositionReference(b?.current)},[b,w.refs]),h.useLayoutEffect(()=>{O&&x?.(w.placement)},[O,w.placement,x]),h.useMemo(()=>({open:O,onOpenChange:j,modal:g,...L,...w}),[O,j,g,L,w])})({...n});return e(b.Provider,{value:o,children:t})},C=h.forwardRef(function({children:n,asChild:o=!1,...s},r){const{refs:a,getReferenceProps:i,open:l,onOpenChange:c}=x(),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})}),F=h.forwardRef(function({style:s,className:r,padding:a=0,initialFocus:i=0,returnFocus:l=!0,...c},u){const{context:p,modal:d,refs:m,open:f,floatingStyles:b,getFloatingProps:k,isPositioned:C}=x(),F=t([m.setFloating,u]),P=m.reference.current,{theme:R,size:y}=v((O=P)&&"contextElement"in O?P.contextElement:P),E=h.useRef(null);var O;return h.useEffect(()=>{E.current=p.elements.domReference?.closest("[data-portal]")||document.body},[p.elements.domReference]),f?e(n,{root:E.current,children:e(o,{context:p,modal:d,initialFocus:i,returnFocus:l,children:e("div",{"data-theme":R,"data-size":y,className:g("jkl jkl-popover",r),ref:F,style:{...s,...b,"--popover-padding":`var(--jkl-spacing-${a})`,visibility:d||C?"visible":"hidden"},...k(c),children:c.children})})}):null});k.Trigger=C,k.Content=F;export{k as Popover,k 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({\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
|
+
{"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 onPlacementChange,\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 // useLayoutEffect (i stedet for useEffect) sikrer at konsumenter får\n // riktig placement før paint — ellers ville første frame bruke default\n // placement og deretter snappe over til den faktiske, noe som gir et\n // synlig \"glitch\" på styling som er placement-avhengig (f.eks. flat side\n // / border-radius på Select-listboxen ved flip).\n React.useLayoutEffect(() => {\n if (!open) return;\n onPlacementChange?.(data.placement);\n }, [open, data.placement, onPlacementChange]);\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 {\n context,\n modal,\n refs,\n open,\n floatingStyles,\n getFloatingProps,\n isPositioned,\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 // Skjul popoveren inntil floating-ui har regnet\n // ut første posisjon — ellers blinker den\n // kort i (0,0) før den hopper på plass.\n // Bare for ikke-modale popovere; modale bruker\n // umiddelbar fokus-trap som forutsetter at\n // innholdet er fokuserbart fra første render.\n visibility:\n modal || isPositioned ? \"visible\" : \"hidden\",\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","onPlacementChange","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","isPositioned","setFloating","referenceElement","reference","theme","size","getThemeAndSize","contextElement","floatingPortalRef","useRef","useEffect","elements","domReference","closest","document","body","FloatingPortal","root","FloatingFocusManager","visibility","Trigger","Content"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReferenceType, UseFloatingOptions, useClick, useDismiss, useFocus, useHover, useRole } from '@floating-ui/react';
|
|
1
|
+
import { Placement, ReferenceType, UseFloatingOptions, useClick, useDismiss, useFocus, useHover, useRole } from '@floating-ui/react';
|
|
2
2
|
export type ClickOptions = Parameters<typeof useClick>[1];
|
|
3
3
|
export type DismissOptions = Parameters<typeof useDismiss>[1];
|
|
4
4
|
export type FocusOptions = Parameters<typeof useFocus>[1];
|
|
@@ -58,6 +58,13 @@ export interface PopoverOptions {
|
|
|
58
58
|
* @default Popover.Trigger
|
|
59
59
|
*/
|
|
60
60
|
positionReference?: React.RefObject<ReferenceType>;
|
|
61
|
+
/**
|
|
62
|
+
* Trigges når popoverens faktiske plassering endrer seg, f.eks. når
|
|
63
|
+
* `flip`-middlewaren snur popoveren over triggeren fordi det ikke er
|
|
64
|
+
* plass under. Kan brukes til å justere styling avhengig av om
|
|
65
|
+
* popoveren ligger over eller under referansen.
|
|
66
|
+
*/
|
|
67
|
+
onPlacementChange?: (placement: Placement) => void;
|
|
61
68
|
/**
|
|
62
69
|
* Options for hover-interaksjoner.
|
|
63
70
|
*
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{jsxs as e,Fragment as t,jsx as
|
|
1
|
+
import{jsxs as e,Fragment as t,jsx as r}from"react/jsx-runtime";import{c as o}from"../../../clsx-BeLtu-UY.js";import n,{forwardRef as a,useState as l,useCallback as s,useMemo as i,useRef as c,useEffect as u}from"react";import{useId as p}from"../../hooks/useId/useId.js";import{useListNavigation as d}from"../../hooks/useListNavigation/useListNavigation.js";import{usePreviousValue as v}from"../../hooks/usePreviousValue/usePreviousValue.js";import{getValuePair as m}from"../../utilities/valuePair.js";import{ArrowVerticalAnimated as f}from"../icon/icons/animated/ArrowVerticalAnimated.js";import{InputGroup as b}from"../input-group/InputGroup.js";import{Popover as h}from"../popover/Popover.js";import{focusSelected as g,toLower as k}from"./select-utils.js";const y=()=>{},w=a((a,w)=>{const{id:j,name:_,items:P,value:D,label:E,labelProps:$,onChange:L,onBlur:N,onFocus:x,className:C,helpLabel:F,errorLabel:A,invalid:S,searchable:V=!1,inline:T=!1,defaultPrompt:I="Velg",width:O,maxShownOptions:K=5,style:B,tooltip:M,...q}=a,z=p(j||"jkl-select",{generateSuffix:!j}),G=`${z}_label`,R=`${z}_button`,U=`${z}_search-input`,W=`--${z.replace(/[^a-zA-Z0-9-]/g,"-")}-anchor`,[Z,H]=l(!1),J=s(()=>{H(e=>!e)},[]),[Q,X]=l("bottom"),Y=s(e=>{X(e.startsWith("top")?"top":"bottom")},[]),ee=!!V,te=ee&&Z,[re,oe]=l(""),ne=s(e=>!!e.label.toLowerCase().includes(re.toLowerCase())||"function"==typeof V&&V(re,e),[V,re]),ae=i(()=>P.map(m).map(e=>{const t=!ee||""===re||ne(e);return{...e,visible:t}}),[P,ee,re,ne]),le=i(()=>!(typeof D>"u")&&P.some(e=>"string"==typeof e?e===D:e.value===D),[D,P]),[se,ie]=l(le&&void 0!==D?D:""),ce=""!==se,ue=i(()=>ae.find(e=>e.value===se)?.label||I,[ae,se,I]),pe=c(null),de=s(e=>{pe.current=e,w&&("function"==typeof w?w(e):w.current=e),e&&ie(e.value)},[w]),ve=v(D);u(()=>{D!==ve&&ie(typeof D>"u"||!le?"":D)},[D,ve,le]);const me=s(e=>{const t=e.value;oe(""),ie(t),J(),ke.current?.focus()},[J]),fe=v(se);u(()=>{typeof fe>"u"||fe===se||se===D||(L&&L({type:"change",target:{name:_,value:se}}),pe.current&&pe.current.dispatchEvent(new Event("change",{bubbles:!0})))},[L,_,D,se,fe]);const be=c(null),he=c(!1),ge=c(null),ke=c(null),ye=c(null),[we,je]=l(null),_e=c(ee),Pe=c(se);u(()=>{_e.current=ee,Pe.current=se});const De=s(e=>{ye.current=e,je(e),e&&!_e.current&&requestAnimationFrame(()=>{ye.current===e&&g(e,Pe.current)})},[]),Ee=v(Z);u(()=>{Z!==Ee&&(Z&&ee?ge.current?.focus():!Z&&he.current&&ke.current&&ke.current.focus())},[Z,Ee,ee]),d({element:we});const $e=s(()=>{ee&&oe(""),N&&(N({type:"blur",target:{name:_,value:se}}),pe.current?.dispatchEvent(new Event("focusout",{bubbles:!0}))),he.current=!1,H(!1)},[N,ee,_,se]),Le=s(e=>{const t=be.current,r=ye.current;t?.contains(e.relatedTarget)||r?.contains(e.relatedTarget)||$e()},[$e]),Ne=s(()=>{he.current||(x&&x({type:"change",target:{name:_,value:se}}),he.current=!0)},[x,se,_]),xe=s(e=>{e.target.focus({preventScroll:!0})},[]);u(()=>{const e=pe.current;if(!e)return;const t=()=>{te?ge.current?.focus():ke.current?.focus()},r=e=>{const t=e.relatedTarget,r=be.current?.contains(t),o=ye.current?.contains(t);(r||o)&&e.preventDefault()};return e.addEventListener("focus",t),e.addEventListener("blur",r),()=>{e.removeEventListener("focus",t),e.removeEventListener("blur",r)}},[te]);const Ce=s(e=>{"ArrowDown"!==e.key&&" "!==e.key||Z?"Escape"===e.key&&(e.preventDefault(),e.stopPropagation(),H(!1)):(e.preventDefault(),e.stopPropagation(),H(!0))},[Z]),Fe=s(e=>{if("ArrowDown"===e.key){e.preventDefault(),e.stopPropagation();const t=ye.current;t&&g(t,ee?void 0:se)}else if("Escape"===e.key)e.preventDefault(),e.stopPropagation(),H(!1);else if("Tab"!==e.key||e.shiftKey)"Enter"===e.key&&Z&&(e.preventDefault(),e.stopPropagation());else{const t=ye.current;t&&(e.preventDefault(),e.stopPropagation(),g(t,se))}},[se,ee,Z]),Ae=s(e=>{if("Tab"===e.key)e.preventDefault(),e.stopPropagation(),e.shiftKey&&ge.current?ge.current.focus():ke.current&&(ie(e.currentTarget.value),H(!1),ke.current.focus());else if("ArrowUp"===e.key&&ye.current&&ge.current){const t=ye.current.querySelector('[role="option"]:not([hidden])');e.currentTarget.id===t?.id&&ge.current&&ge.current.focus()}},[]);return u(()=>{const e=e=>{"Escape"===e.key&&Z&&H(!1)};return typeof window<"u"&&Z&&window.addEventListener("keydown",e),()=>{typeof window<"u"&&window.removeEventListener("keydown",e)}},[Z]),e(t,{children:[e("select",{name:_,tabIndex:-1,"data-testid":"jkl-native-select",className:"jkl-sr-only","aria-hidden":!0,ref:de,value:se,onChange:y,children:[r("option",{value:""})," ",ae.map(e=>r("option",{hidden:!e.visible,value:e.value,children:e.label},`${z}-opt-${e.value}`))]}),r(b,{ref:be,"data-testid":"jkl-select",className:o("jkl-select",C,{"jkl-select--inline":T,"jkl-select--open":Z&&ae.some(e=>e.visible),"jkl-select--no-value":!ce,"jkl-select--invalid":!!A||S}),tooltip:M&&n.isValidElement(M)?n.cloneElement(M,{triggerProps:{...M.props.triggerProps,onFocus:e=>{M.props.triggerProps?.onFocus?.(e),$e()}}}):null,...q,id:ee?U:R,style:B,label:E,labelProps:{id:G,srOnly:T,...$,htmlFor:ee?U:R},helpLabel:F,errorLabel:A,render:({"aria-invalid":t,...n})=>{const a=Z&&ae.some(e=>e.visible);return e(h,{open:a,placement:"bottom-start",offset:0,modal:!1,onPlacementChange:Y,clickOptions:{enabled:!1},dismissOptions:{enabled:!1},roleOptions:{enabled:!1},children:[r(h.Trigger,{asChild:!0,children:e("div",{className:"jkl-select__outer-wrapper","data-popover-placement":Q,style:{width:O,anchorName:W},children:[ee&&r("input",{...n,"aria-invalid":t,id:U,hidden:!te,ref:ge,placeholder:"Søk",value:re,onChange:e=>oe(e.target.value),"data-testid":"jkl-select__search-input",className:"jkl-select__search-input","aria-autocomplete":"list","aria-activedescendant":a&&ce?`${z}__${k(se)}`:void 0,"aria-controls":a?z:void 0,"aria-expanded":a,role:"combobox",onKeyDown:Fe,onBlur:Le,onFocus:Ne,onClick:e=>{e.stopPropagation()}}),r("button",{"aria-invalid":t,...n,id:R,ref:ke,hidden:te,type:"button",name:`${_}-btn`,className:o("jkl-select__button",{"jkl-select__button--active-value":!!se}),"data-testid":"jkl-select__button","aria-label":`${ue||"Velg"},${E}`,"aria-expanded":a,"aria-controls":a?z:void 0,onBlur:Le,onFocus:Ne,onKeyDown:Ce,onClick:J,onMouseDown:e=>{e.preventDefault(),ke.current?.focus()},children:ue}),r(f,{variant:"medium",pointingDown:!a,className:"jkl-select__arrow"})]})}),r(h.Content,{initialFocus:-1,returnFocus:!1,className:"jkl-select__popover",style:{width:`anchor-size(${W} width)`},children:r("div",{id:z,ref:De,role:"listbox",className:"jkl-select__options-menu","data-popover-placement":Q,"aria-labelledby":G,tabIndex:-1,"data-focus":"controlled",style:{"--jkl-select-max-shown-options":K},children:ae.map((t,o)=>t.visible?e("button",{hidden:!t.visible,type:"button",id:`${z}__${k(t.value)}`,className:"jkl-select__option","data-testid":"jkl-select__option","aria-selected":t.value===se,role:"option",value:t.value,"data-testautoid":`jkl-select__option-${o}`,onBlur:Le,onFocus:Ne,onKeyDown:Ae,onClick:e=>{e.preventDefault(),me(t)},onMouseOver:xe,children:[t.label,t.description?r("span",{className:"jkl-select__option-description",children:t.description}):null]},`${z}-${t.value}`):null)})})]})}})]})});w.displayName="Select";export{w as Select};
|
|
2
2
|
//# sourceMappingURL=Select.js.map
|