@ahrowe/ui 0.31.0 → 0.33.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.
- package/dist/esm/common/actionButtons/actionButtons.mjs +1 -1
- package/dist/esm/common/actionButtons/actionButtons.mjs.map +1 -1
- package/dist/esm/common/alert/alert.mjs +1 -1
- package/dist/esm/common/alert/alert.mjs.map +1 -1
- package/dist/esm/common/alert/alert.types.mjs.map +1 -1
- package/dist/esm/common/breadcrumb/breadcrumb.mjs +1 -1
- package/dist/esm/common/breadcrumb/breadcrumb.mjs.map +1 -1
- package/dist/esm/common/card/Card.mjs +1 -1
- package/dist/esm/common/card/Card.mjs.map +1 -1
- package/dist/esm/common/card/card.types.mjs.map +1 -1
- package/dist/esm/common/carousel/carousel.mjs +1 -1
- package/dist/esm/common/carousel/carousel.mjs.map +1 -1
- package/dist/esm/common/chip/chip.mjs +1 -1
- package/dist/esm/common/chip/chip.mjs.map +1 -1
- package/dist/esm/common/chip/chip.types.mjs.map +1 -1
- package/dist/esm/common/colorPicker/colorPicker.mjs +1 -1
- package/dist/esm/common/colorPicker/colorPicker.mjs.map +1 -1
- package/dist/esm/common/configProvider/useLabels.mjs +2 -0
- package/dist/esm/common/configProvider/useLabels.mjs.map +1 -0
- package/dist/esm/common/confirmModal/confirmModal.mjs +1 -1
- package/dist/esm/common/confirmModal/confirmModal.mjs.map +1 -1
- package/dist/esm/common/datePicker/components/datePickerMonth/datePickerMonth.mjs +1 -1
- package/dist/esm/common/datePicker/components/datePickerMonth/datePickerMonth.mjs.map +1 -1
- package/dist/esm/common/datePicker/datePicker.mjs +1 -1
- package/dist/esm/common/datePicker/datePicker.mjs.map +1 -1
- package/dist/esm/common/drawer/drawer.mjs +1 -1
- package/dist/esm/common/drawer/drawer.mjs.map +1 -1
- package/dist/esm/common/dropdown/dropdown.mjs +1 -1
- package/dist/esm/common/dropdown/dropdown.mjs.map +1 -1
- package/dist/esm/common/emptyState/emptyState.mjs +1 -1
- package/dist/esm/common/emptyState/emptyState.mjs.map +1 -1
- package/dist/esm/common/fab/components/fabBase/fabBase.mjs +1 -1
- package/dist/esm/common/fab/components/fabBase/fabBase.mjs.map +1 -1
- package/dist/esm/common/fab/fab.mjs +1 -1
- package/dist/esm/common/fab/fab.mjs.map +1 -1
- package/dist/esm/common/infiniteBlock/infiniteBlock.mjs +1 -1
- package/dist/esm/common/infiniteBlock/infiniteBlock.mjs.map +1 -1
- package/dist/esm/common/input/input.mjs +1 -1
- package/dist/esm/common/input/input.mjs.map +1 -1
- package/dist/esm/common/input/input.types.mjs.map +1 -1
- package/dist/esm/common/klipyPicker/klipyPicker.mjs +1 -1
- package/dist/esm/common/klipyPicker/klipyPicker.mjs.map +1 -1
- package/dist/esm/common/modal/modal.mjs +1 -1
- package/dist/esm/common/modal/modal.mjs.map +1 -1
- package/dist/esm/common/multiSelect/multiSelect.mjs +1 -1
- package/dist/esm/common/multiSelect/multiSelect.mjs.map +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs.map +1 -1
- package/dist/esm/common/otpInput/otpInput.mjs +1 -1
- package/dist/esm/common/otpInput/otpInput.mjs.map +1 -1
- package/dist/esm/common/otpInput/otpInput.types.mjs.map +1 -1
- package/dist/esm/common/pagination/pagination.mjs +1 -1
- package/dist/esm/common/pagination/pagination.mjs.map +1 -1
- package/dist/esm/common/progressBar/progressBar.mjs +1 -1
- package/dist/esm/common/progressBar/progressBar.mjs.map +1 -1
- package/dist/esm/common/roomDrawer/roomDrawer.mjs +1 -1
- package/dist/esm/common/roomDrawer/roomDrawer.mjs.map +1 -1
- package/dist/esm/common/searchInput/searchInput.mjs +1 -1
- package/dist/esm/common/searchInput/searchInput.mjs.map +1 -1
- package/dist/esm/common/splitButton/splitButton.mjs +1 -1
- package/dist/esm/common/splitButton/splitButton.mjs.map +1 -1
- package/dist/esm/common/timer/timer.mjs +1 -1
- package/dist/esm/common/timer/timer.mjs.map +1 -1
- package/dist/esm/common/toast/toast.mjs +1 -1
- package/dist/esm/common/toast/toast.mjs.map +1 -1
- package/dist/esm/common/toast/toastProvider.mjs +1 -1
- package/dist/esm/common/toast/toastProvider.mjs.map +1 -1
- package/dist/esm/common/tree/tree.mjs +1 -1
- package/dist/esm/common/tree/tree.mjs.map +1 -1
- package/dist/esm/common/virtualList/virtualList.mjs +1 -1
- package/dist/esm/common/virtualList/virtualList.mjs.map +1 -1
- package/dist/esm/common/virtualList/virtualListHeader.mjs +1 -1
- package/dist/esm/common/virtualList/virtualListHeader.mjs.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/types/common/actionButtons/actionButtons.types.d.ts +9 -2
- package/dist/types/common/alert/alert.types.d.ts +7 -0
- package/dist/types/common/breadcrumb/breadcrumb.types.d.ts +7 -0
- package/dist/types/common/card/card.types.d.ts +6 -1
- package/dist/types/common/carousel/carousel.types.d.ts +13 -0
- package/dist/types/common/chip/chip.types.d.ts +13 -2
- package/dist/types/common/colorPicker/colorPicker.d.ts +1 -1
- package/dist/types/common/colorPicker/colorPicker.types.d.ts +13 -1
- package/dist/types/common/configProvider/configProvider.types.d.ts +26 -1
- package/dist/types/common/configProvider/index.d.ts +1 -0
- package/dist/types/common/configProvider/useLabels.d.ts +22 -0
- package/dist/types/common/confirmModal/confirmModal.types.d.ts +13 -4
- package/dist/types/common/datePicker/components/datePickerMonth/datePickerMonth.d.ts +2 -14
- package/dist/types/common/datePicker/components/datePickerMonth/datePickerMonth.types.d.ts +23 -0
- package/dist/types/common/datePicker/datePicker.d.ts +1 -22
- package/dist/types/common/datePicker/datePicker.types.d.ts +60 -0
- package/dist/types/common/datePicker/index.d.ts +1 -0
- package/dist/types/common/drawer/drawer.d.ts +1 -1
- package/dist/types/common/drawer/drawer.types.d.ts +7 -1
- package/dist/types/common/dropdown/dropdown.types.d.ts +6 -6
- package/dist/types/common/emptyState/emptyState.d.ts +1 -1
- package/dist/types/common/emptyState/emptyState.types.d.ts +13 -1
- package/dist/types/common/fab/components/fabBase/fabBase.d.ts +1 -1
- package/dist/types/common/fab/components/fabBase/fabBase.types.d.ts +3 -1
- package/dist/types/common/fab/fab.d.ts +1 -1
- package/dist/types/common/fab/fab.types.d.ts +6 -1
- package/dist/types/common/infiniteBlock/infiniteBlock.d.ts +1 -1
- package/dist/types/common/infiniteBlock/infiniteBlock.types.d.ts +2 -0
- package/dist/types/common/input/input.types.d.ts +13 -0
- package/dist/types/common/klipyPicker/klipyPicker.d.ts +1 -1
- package/dist/types/common/klipyPicker/klipyPicker.types.d.ts +7 -0
- package/dist/types/common/modal/modal.types.d.ts +7 -0
- package/dist/types/common/multiSelect/multiSelect.types.d.ts +13 -6
- package/dist/types/common/numberInput/numberInput.types.d.ts +15 -2
- package/dist/types/common/otpInput/otpInput.types.d.ts +9 -0
- package/dist/types/common/pagination/pagination.types.d.ts +15 -0
- package/dist/types/common/progressBar/progressBar.d.ts +1 -1
- package/dist/types/common/progressBar/progressBar.types.d.ts +6 -1
- package/dist/types/common/roomDrawer/roomDrawer.types.d.ts +6 -0
- package/dist/types/common/searchInput/searchInput.d.ts +1 -1
- package/dist/types/common/searchInput/searchInput.types.d.ts +13 -1
- package/dist/types/common/splitButton/splitButton.types.d.ts +7 -0
- package/dist/types/common/timer/timer.types.d.ts +7 -0
- package/dist/types/common/toast/toast.d.ts +4 -2
- package/dist/types/common/toast/toast.types.d.ts +11 -1
- package/dist/types/common/toast/toastProvider.d.ts +1 -1
- package/dist/types/common/tree/tree.types.d.ts +7 -2
- package/dist/types/common/virtualList/virtualList.types.d.ts +15 -6
- package/dist/types/common/virtualList/virtualListHeader.d.ts +3 -3
- package/docs/ActionButtons.md +7 -6
- package/docs/Alert.md +2 -0
- package/docs/Breadcrumb.md +2 -0
- package/docs/Card.md +2 -0
- package/docs/Carousel.md +2 -0
- package/docs/Chip.md +5 -1
- package/docs/ColorPicker.md +4 -0
- package/docs/ConfigProvider.md +23 -0
- package/docs/ConfirmModal.md +7 -5
- package/docs/DatePicker.md +6 -1
- package/docs/Drawer.md +2 -0
- package/docs/Dropdown.md +2 -0
- package/docs/EmptyState.md +4 -0
- package/docs/Fab.md +2 -0
- package/docs/FormValidatorGroup.md +1 -1
- package/docs/Input.md +2 -0
- package/docs/KlipyPicker.md +2 -0
- package/docs/Modal.md +2 -0
- package/docs/MultiSelect.md +7 -5
- package/docs/NumberInput.md +8 -2
- package/docs/OtpInput.md +2 -0
- package/docs/Pagination.md +2 -0
- package/docs/ProgressBar.md +2 -0
- package/docs/RoomDrawer.md +2 -0
- package/docs/SearchInput.md +4 -0
- package/docs/SplitButton.md +2 -0
- package/docs/Timer.md +2 -0
- package/docs/Toast.md +2 -0
- package/docs/Tree.md +3 -1
- package/docs/VirtualList.md +3 -2
- package/docs/Wizard.md +1 -2
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLabels.mjs","names":[],"sources":["../../../../package/common/configProvider/useLabels.ts"],"sourcesContent":["import { useContext } from 'react';\n\nimport { ConfigContext } from './configProvider';\nimport type { ComponentDefaults } from './configProvider.types';\n\n/**\n * Resolves the text a component renders of its own, per key, from three places:\n * the component's built-in English, the nearest `ConfigProvider`, and the\n * instance's `labels` prop, in that order of increasing precedence.\n *\n * Per key is the point, and the reason this exists next to `useComponentDefaults`\n * rather than relying on it. That one fills in whole props: a `labels` object on\n * an instance would replace the provider's entirely, so translating an app once\n * and overriding a single string on one instance would silently drop every other\n * translation for that component.\n *\n * ```tsx\n * const DEFAULT_LABELS: Required<ModalLabels> = { close: 'Close' };\n *\n * function Modal({ labels, ...rest }: ModalProps) {\n * const text = useLabels('Modal', labels, DEFAULT_LABELS);\n * // text.close\n * }\n * ```\n */\nexport function useLabels<L extends object>(\n component: keyof ComponentDefaults,\n labels: Partial<L> | undefined,\n defaults: L,\n): L {\n const ctx = useContext(ConfigContext);\n const global = (ctx?.[component] as { labels?: Partial<L> } | undefined)?.labels;\n // Not memoised on purpose: `defaults` and `labels` are object literals at every\n // call site, so a dependency list would never hit and the bookkeeping would\n // cost more than three spreads of a handful of strings.\n return { ...defaults, ...global, ...labels };\n}\n"],"mappings":"wFAyBA,SAAgB,EACd,EACA,EACA,EACG,CAEH,IAAM,EADM,EAAW,CACP,CAAA,GAAM,EAAA,EAAoD,OAI1E,MAAO,CAAE,GAAG,EAAU,GAAG,EAAQ,GAAG,CAAO,CAC7C"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{
|
|
1
|
+
import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{ButtonStyleType as n}from"../button/button.types.mjs";import r from"../actionButtons/actionButtons.mjs";import i from"../modal/modal.mjs";import{useState as a}from"react";import{jsx as o,jsxs as s}from"react/jsx-runtime";var c={submit:`Confirm`,cancel:`Cancel`};function l(l){let{children:u=null,className:d=``,onClose:f=()=>{},onConfirm:p=()=>{},title:m=``,content:h=null,isOpen:g=void 0,labels:_,isDelete:v=!1,actionButtonsProps:y={},style:b,...x}=e(`ConfirmModal`,l),S=t(`ConfirmModal`,_,c),[C,w]=a(!1),[T,E]=a(!1);function D(e=!1){w(!1),f(e)}async function O(){E(!0);try{await p(),D(!0)}catch{}finally{E(!1)}}let k=s(i,{title:m,isOpen:g===void 0?C:g,onClose:()=>D(),className:u?void 0:d,children:[h,o(r,{onClose:()=>D(),onSubmit:O,labels:{submit:S.submit,cancel:S.cancel},submitButtonStyle:v?n.Delete:void 0,isSubmitButtonLoading:T,...y})]});return u?s(`div`,{...x,className:d,style:b,children:[o(`span`,{onClick:()=>w(!0),children:u}),k]}):k}export{l as default};
|
|
2
2
|
//# sourceMappingURL=confirmModal.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirmModal.mjs","names":[],"sources":["../../../../package/common/confirmModal/confirmModal.tsx"],"sourcesContent":["import { useState, type ReactElement } from 'react';\n\nimport Modal from '../modal';\nimport { ActionButtons } from '../actionButtons';\nimport { ButtonStyleType } from '../button';\nimport { useComponentDefaults } from '../configProvider';\nimport type { ConfirmModalProps } from './confirmModal.types';\n\nfunction ConfirmModal(props: ConfirmModalProps): ReactElement {\n const {\n children = null,\n className = '',\n onClose = () => {},\n onConfirm = () => {},\n title = '',\n content = null,\n isOpen: propIsOpen = undefined,\n
|
|
1
|
+
{"version":3,"file":"confirmModal.mjs","names":[],"sources":["../../../../package/common/confirmModal/confirmModal.tsx"],"sourcesContent":["import { useState, type ReactElement } from 'react';\n\nimport Modal from '../modal';\nimport { ActionButtons } from '../actionButtons';\nimport { ButtonStyleType } from '../button';\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport type { ConfirmModalLabels, ConfirmModalProps } from './confirmModal.types';\n\nconst DEFAULT_LABELS: Required<ConfirmModalLabels> = {\n submit: 'Confirm',\n cancel: 'Cancel',\n};\n\nfunction ConfirmModal(props: ConfirmModalProps): ReactElement {\n const {\n children = null,\n className = '',\n onClose = () => {},\n onConfirm = () => {},\n title = '',\n content = null,\n isOpen: propIsOpen = undefined,\n labels,\n isDelete = false,\n actionButtonsProps = {},\n style,\n ...rest\n } = useComponentDefaults('ConfirmModal', props);\n const text = useLabels('ConfirmModal', labels, DEFAULT_LABELS);\n const [internalOpen, setInternalOpen] = useState(false);\n const [isSubmitting, setIsSubmitting] = useState(false);\n\n function handleClose(didSubmit = false) {\n setInternalOpen(false);\n onClose(didSubmit);\n }\n\n async function handleConfirm() {\n setIsSubmitting(true);\n try {\n await onConfirm();\n handleClose(true);\n } catch {\n // Nothing is awaiting this handler, so a rejection would surface as an unhandled one.\n // The dialog staying open is the signal that the action did not go through; reporting\n // the failure itself belongs to whoever wrote `onConfirm`.\n } finally {\n setIsSubmitting(false);\n }\n }\n\n const isOpen = propIsOpen === undefined ? internalOpen : propIsOpen;\n\n const modal = (\n <Modal title={title} isOpen={isOpen} onClose={() => handleClose()} className={children ? undefined : className}>\n {content}\n <ActionButtons\n onClose={() => handleClose()}\n onSubmit={handleConfirm}\n labels={{ submit: text.submit, cancel: text.cancel }}\n submitButtonStyle={isDelete ? ButtonStyleType.Delete : undefined}\n isSubmitButtonLoading={isSubmitting}\n {...actionButtonsProps}\n />\n </Modal>\n );\n\n if (!children) return modal;\n\n return (\n <div {...rest} className={className} style={style}>\n <span onClick={() => setInternalOpen(true)}>{children}</span>\n {modal}\n </div>\n );\n}\n\nexport default ConfirmModal;\n"],"mappings":"kXAQA,IAAM,EAA+C,CACnD,OAAQ,UACR,OAAQ,QACV,EAEA,SAAS,EAAa,EAAwC,CAC5D,GAAM,CACJ,WAAW,KACX,YAAY,GACZ,cAAgB,CAAC,EACjB,gBAAkB,CAAC,EACnB,QAAQ,GACR,UAAU,KACV,OAAQ,EAAa,IAAA,GACrB,SACA,WAAW,GACX,qBAAqB,CAAC,EACtB,QACA,GAAG,GACD,EAAqB,eAAgB,CAAK,EACxC,EAAO,EAAU,eAAgB,EAAQ,CAAc,EACvD,CAAC,EAAc,GAAmB,EAAS,EAAK,EAChD,CAAC,EAAc,GAAmB,EAAS,EAAK,EAEtD,SAAS,EAAY,EAAY,GAAO,CACtC,EAAgB,EAAK,EACrB,EAAQ,CAAS,CACnB,CAEA,eAAe,GAAgB,CAC7B,EAAgB,EAAI,EACpB,GAAI,CACF,MAAM,EAAU,EAChB,EAAY,EAAI,CAClB,MAAQ,CAIR,QAAU,CACR,EAAgB,EAAK,CACvB,CACF,CAIA,IAAM,EACJ,EAAC,EAAD,CAAc,QAAe,OAHhB,IAAe,IAAA,GAAY,EAAe,EAGlB,YAAe,EAAY,EAAG,UAAW,EAAW,IAAA,GAAY,EAArG,SAAA,CACG,EACD,EAAC,EAAD,CACE,YAAe,EAAY,EAC3B,SAAU,EACV,OAAQ,CAAE,OAAQ,EAAK,OAAQ,OAAQ,EAAK,MAAO,EACnD,kBAAmB,EAAW,EAAgB,OAAS,IAAA,GACvD,sBAAuB,EACvB,GAAI,CACL,CAAA,CACI,IAKT,OAFK,EAGH,EAAC,MAAD,CAAK,GAAI,EAAiB,YAAkB,QAA5C,SAAA,CACE,EAAC,OAAD,CAAM,YAAe,EAAgB,EAAI,EAAI,UAAe,CAAA,EAC3D,CACE,IANe,CAQxB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"../../../interactableDiv/index.mjs";import t from"./datePickerMonth.module.mjs";import{getLocale as n}from"../../../../services/localization.mjs";import{addDays as r,getDateFromDayMonthAndYear as i,getDayMonthAndYearOfDate as a,getDaysInMonth as o,getStartWeekDayOfMonth as s,getWeekDays as c}from"../../dateFunctions.mjs";import{useEffect as l,useRef as u,useState as d}from"react";import f from"classnames";import{jsx as p,jsxs as m}from"react/jsx-runtime";function h(e,t,n){if(n){let r=a(n);if(r.month===e&&r.year===t)return r.day}let r=a(new Date);return r.month===e&&r.year===t?r.day:1}function g(e,t,n,r,o){let{day:s,month:c,year:l}=r?a(r):{day:void 0,month:void 0,year:void 0},{day:u,month:d,year:f}=o?a(o):{day:void 0,month:void 0,year:void 0},p=i(e,t,n),m=e===s&&t===c&&n===l,h=e===u&&t===d&&n===f,g=!1;if(s!==void 0&&c!==void 0&&l!==void 0&&u!==void 0&&d!==void 0&&f!==void 0){let e=i(s,c,l),t=i(u,d,f);g=p.getTime()>=e.getTime()&&p.getTime()<=t.getTime()}return{isStartDate:m,isInRange:g,isEndDate:h}}function _(e,t,n,r,o){let s=i(e,t,n);if(r){let{day:e,month:t,year:n}=a(r);if(s<i(e,t,n))return!0}if(o){let{day:e,month:t,year:n}=a(o);if(s>i(e,t,n))return!0}return!1}function v(e,t,n){let{day:r,month:i,year:o}=a(new Date);return e===r&&t===i&&n===o}function y({className:
|
|
1
|
+
import e from"../../../interactableDiv/index.mjs";import t from"./datePickerMonth.module.mjs";import{getLocale as n}from"../../../../services/localization.mjs";import{addDays as r,getDateFromDayMonthAndYear as i,getDayMonthAndYearOfDate as a,getDaysInMonth as o,getStartWeekDayOfMonth as s,getWeekDays as c}from"../../dateFunctions.mjs";import{useEffect as l,useRef as u,useState as d}from"react";import f from"classnames";import{jsx as p,jsxs as m}from"react/jsx-runtime";function h(e,t,n){if(n){let r=a(n);if(r.month===e&&r.year===t)return r.day}let r=a(new Date);return r.month===e&&r.year===t?r.day:1}function g(e,t,n,r,o){let{day:s,month:c,year:l}=r?a(r):{day:void 0,month:void 0,year:void 0},{day:u,month:d,year:f}=o?a(o):{day:void 0,month:void 0,year:void 0},p=i(e,t,n),m=e===s&&t===c&&n===l,h=e===u&&t===d&&n===f,g=!1;if(s!==void 0&&c!==void 0&&l!==void 0&&u!==void 0&&d!==void 0&&f!==void 0){let e=i(s,c,l),t=i(u,d,f);g=p.getTime()>=e.getTime()&&p.getTime()<=t.getTime()}return{isStartDate:m,isInRange:g,isEndDate:h}}function _(e,t,n,r,o){let s=i(e,t,n);if(r){let{day:e,month:t,year:n}=a(r);if(s<i(e,t,n))return!0}if(o){let{day:e,month:t,year:n}=a(o);if(s>i(e,t,n))return!0}return!1}function v(e,t,n){let{day:r,month:i,year:o}=a(new Date);return e===r&&t===i&&n===o}function y({style:a,className:y=``,month:b=new Date().getMonth()+1,year:x=new Date().getFullYear(),onSelect:S=()=>null,selectionStart:C,selectionEnd:w,minDate:T=null,maxDate:E=null,onNavigateMonth:D}){let O=n(`-`),k=o(b,x),A=s(b,x),j=u({}),[M,N]=d(()=>h(b,x,C)),P=u(null);l(()=>{if(P.current!=null){let e=P.current;P.current=null,N(e),j.current[e]?.focus()}else N(h(b,x,C))},[b,x]);function F(e,t){let n=0;if(e.key===`ArrowRight`)n=1;else if(e.key===`ArrowLeft`)n=-1;else if(e.key===`ArrowDown`)n=7;else if(e.key===`ArrowUp`)n=-7;else return;e.preventDefault();let i=r(t,b,x,n);i.month!==b||i.year!==x?(P.current=i.day,D?.(i.month>b||i.year>x?1:-1)):(N(i.day),j.current[i.day]?.focus())}return p(`div`,{className:f(t.datePickerMonth,y),style:a,children:m(`div`,{className:f(t.datePickerMonthContent),children:[c(O).map((e,t)=>p(`div`,{children:e},t)),Array.from(Array(A-1).keys()).map(e=>p(`div`,{className:f(t.datePickerMonthItem,t.datePickerMonthPlaceholder)},e)),Array.from(Array(k).keys()).map(n=>{let r=n+1,a=g(r,b,x,C,w),o=_(r,b,x,T,E),s=v(r,b,x);return p(e,{ref:e=>{j.current[r]=e},tabIndex:r===M?0:-1,onKeyDown:e=>F(e,r),onClick:()=>o?null:S(i(r,b,x)),className:f(t.datePickerMonthDay,t.datePickerMonthItem,{[t.datePickerMonthDaySelected]:a.isInRange,[t.datePickerMonthDaySelectedStart]:a.isStartDate,[t.datePickerMonthDaySelectedEnd]:a.isEndDate,[t.datePickerMonthDayDisabled]:o,[t.datePickerMonthDayToday]:s}),children:r},r)}),Array.from(Array(42-(A+k-1)).keys()).map(e=>p(`div`,{className:f(t.datePickerMonthItem,t.datePickerMonthPlaceholder),children:`\xA0`},e))]})})}export{y as default};
|
|
2
2
|
//# sourceMappingURL=datePickerMonth.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datePickerMonth.mjs","names":[],"sources":["../../../../../../package/common/datePicker/components/datePickerMonth/datePickerMonth.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\n\nimport styles from './datePickerMonth.module.pcss';\nimport { getLocale } from 'services/localization';\nimport InteractableDiv from 'components/common/interactableDiv';\nimport {\n addDays,\n getDateFromDayMonthAndYear,\n getDayMonthAndYearOfDate,\n getDaysInMonth,\n getStartWeekDayOfMonth,\n getWeekDays,\n} from '../../dateFunctions';\n\ninterface DatePickerMonthProps {\n className?: string;\n month?: number;\n year?: number;\n onSelect?: (date: Date) => void;\n selectionStart?: Date;\n selectionEnd?: Date;\n minDate?: Date | null;\n maxDate?: Date | null;\n /** Called to shift the displayed month by ±1 when arrow navigation runs past its edge. */\n onNavigateMonth?: (delta: 1 | -1) => void;\n}\n\n// Which day gets the sole tab stop when this month first renders (or when the displayed\n// month changes via the header, not via arrow navigation): the selected day if it falls in\n// this month, else today if it falls in this month, else the 1st.\nfunction getDefaultFocusedDay(month: number, year: number, selectionStart: Date | undefined): number {\n if (selectionStart) {\n const sel = getDayMonthAndYearOfDate(selectionStart);\n if (sel.month === month && sel.year === year) return sel.day;\n }\n const today = getDayMonthAndYearOfDate(new Date());\n if (today.month === month && today.year === year) return today.day;\n return 1;\n}\n\nfunction checkSelected(\n day: number,\n month: number,\n year: number,\n selectionStart: Date | undefined,\n selectionEnd: Date | undefined,\n) {\n const {\n day: startDay,\n month: startMonth,\n year: startYear,\n } = selectionStart ? getDayMonthAndYearOfDate(selectionStart) : { day: undefined, month: undefined, year: undefined };\n const {\n day: endDay,\n month: endMonth,\n year: endYear,\n } = selectionEnd ? getDayMonthAndYearOfDate(selectionEnd) : { day: undefined, month: undefined, year: undefined };\n\n const toCheckNoTime = getDateFromDayMonthAndYear(day, month, year);\n\n const isStartDate = day === startDay && month === startMonth && year === startYear;\n const isEndDate = day === endDay && month === endMonth && year === endYear;\n\n let isInRange = false;\n if (\n startDay !== undefined &&\n startMonth !== undefined &&\n startYear !== undefined &&\n endDay !== undefined &&\n endMonth !== undefined &&\n endYear !== undefined\n ) {\n const selectionStartNoTime = getDateFromDayMonthAndYear(startDay, startMonth, startYear);\n const selectionEndNoTime = getDateFromDayMonthAndYear(endDay, endMonth, endYear);\n isInRange =\n toCheckNoTime.getTime() >= selectionStartNoTime.getTime() &&\n toCheckNoTime.getTime() <= selectionEndNoTime.getTime();\n }\n\n return { isStartDate, isInRange, isEndDate };\n}\n\nfunction checkDisabled(\n day: number,\n month: number,\n year: number,\n minDate: Date | null | undefined,\n maxDate: Date | null | undefined,\n): boolean {\n const toCheckNoTime = getDateFromDayMonthAndYear(day, month, year);\n\n if (minDate) {\n const { day: minDay, month: minMonth, year: minYear } = getDayMonthAndYearOfDate(minDate);\n if (toCheckNoTime < getDateFromDayMonthAndYear(minDay, minMonth, minYear)) return true;\n }\n\n if (maxDate) {\n const { day: maxDay, month: maxMonth, year: maxYear } = getDayMonthAndYearOfDate(maxDate);\n if (toCheckNoTime > getDateFromDayMonthAndYear(maxDay, maxMonth, maxYear)) return true;\n }\n\n return false;\n}\n\nfunction checkIsToday(day: number, month: number, year: number): boolean {\n const { day: currDay, month: currMonth, year: currYear } = getDayMonthAndYearOfDate(new Date());\n return day === currDay && month === currMonth && year === currYear;\n}\n\nexport default function DatePickerMonth({\n className = '',\n month = new Date().getMonth() + 1,\n year = new Date().getFullYear(),\n onSelect = () => null,\n selectionStart,\n selectionEnd,\n minDate = null,\n maxDate = null,\n onNavigateMonth,\n}: DatePickerMonthProps) {\n const locale = getLocale('-');\n const daysInMonth = getDaysInMonth(month, year);\n const startWeekDayOfMonth = getStartWeekDayOfMonth(month, year);\n\n const dayRefs = useRef<Record<number, HTMLDivElement | null>>({});\n const [focusedDay, setFocusedDay] = useState(() => getDefaultFocusedDay(month, year, selectionStart));\n\n // A day arrowed onto in an adjacent month, waiting for that month's grid to render so it\n // can be focused. `onNavigateMonth` only shifts `month`/`year` — the actual DOM focus has\n // to happen after this component re-renders with the new days, hence the effect below.\n const pendingFocusDayRef = useRef<number | null>(null);\n\n useEffect(() => {\n if (pendingFocusDayRef.current != null) {\n const day = pendingFocusDayRef.current;\n pendingFocusDayRef.current = null;\n setFocusedDay(day);\n dayRefs.current[day]?.focus();\n } else {\n // The displayed month changed some other way (header chevrons, month/year dropdowns) —\n // re-pick a sensible tab stop, but don't steal focus from whatever the user just used.\n setFocusedDay(getDefaultFocusedDay(month, year, selectionStart));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [month, year]);\n\n function handleDayKeyDown(event: React.KeyboardEvent<HTMLDivElement>, day: number) {\n let delta = 0;\n if (event.key === 'ArrowRight') delta = 1;\n else if (event.key === 'ArrowLeft') delta = -1;\n else if (event.key === 'ArrowDown') delta = 7;\n else if (event.key === 'ArrowUp') delta = -7;\n else return;\n\n event.preventDefault();\n const next = addDays(day, month, year, delta);\n\n if (next.month !== month || next.year !== year) {\n pendingFocusDayRef.current = next.day;\n onNavigateMonth?.(next.month > month || next.year > year ? 1 : -1);\n } else {\n setFocusedDay(next.day);\n dayRefs.current[next.day]?.focus();\n }\n }\n\n return (\n <div className={cx(styles.datePickerMonth, className)}>\n <div className={cx(styles.datePickerMonthContent)}>\n {getWeekDays(locale).map((weekDay, index) => (\n <div key={index}>{weekDay}</div>\n ))}\n {Array.from(Array(startWeekDayOfMonth - 1).keys()).map((index) => (\n <div key={index} className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)} />\n ))}\n {Array.from(Array(daysInMonth).keys()).map((index) => {\n const day = index + 1;\n const selectedRes = checkSelected(day, month, year, selectionStart, selectionEnd);\n const isDisabled = checkDisabled(day, month, year, minDate, maxDate);\n const isToday = checkIsToday(day, month, year);\n\n return (\n <InteractableDiv\n key={day}\n ref={(el) => {\n dayRefs.current[day] = el;\n }}\n tabIndex={day === focusedDay ? 0 : -1}\n onKeyDown={(event) => handleDayKeyDown(event, day)}\n onClick={() => (isDisabled ? null : onSelect(getDateFromDayMonthAndYear(day, month, year)))}\n className={cx(styles.datePickerMonthDay, styles.datePickerMonthItem, {\n [styles.datePickerMonthDaySelected]: selectedRes.isInRange,\n [styles.datePickerMonthDaySelectedStart]: selectedRes.isStartDate,\n [styles.datePickerMonthDaySelectedEnd]: selectedRes.isEndDate,\n [styles.datePickerMonthDayDisabled]: isDisabled,\n [styles.datePickerMonthDayToday]: isToday,\n })}\n >\n {day}\n </InteractableDiv>\n );\n })}\n {Array.from(Array(42 - (startWeekDayOfMonth + daysInMonth - 1)).keys()).map((index) => (\n <div key={index} className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)}>\n \n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"datePickerMonth.mjs","names":[],"sources":["../../../../../../package/common/datePicker/components/datePickerMonth/datePickerMonth.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\n\nimport styles from './datePickerMonth.module.pcss';\nimport { getLocale } from 'services/localization';\nimport InteractableDiv from 'components/common/interactableDiv';\nimport {\n addDays,\n getDateFromDayMonthAndYear,\n getDayMonthAndYearOfDate,\n getDaysInMonth,\n getStartWeekDayOfMonth,\n getWeekDays,\n} from '../../dateFunctions';\nimport type { DatePickerMonthProps } from './datePickerMonth.types';\n\n// Which day gets the sole tab stop when this month first renders (or when the displayed\n// month changes via the header, not via arrow navigation): the selected day if it falls in\n// this month, else today if it falls in this month, else the 1st.\nfunction getDefaultFocusedDay(month: number, year: number, selectionStart: Date | undefined): number {\n if (selectionStart) {\n const sel = getDayMonthAndYearOfDate(selectionStart);\n if (sel.month === month && sel.year === year) return sel.day;\n }\n const today = getDayMonthAndYearOfDate(new Date());\n if (today.month === month && today.year === year) return today.day;\n return 1;\n}\n\nfunction checkSelected(\n day: number,\n month: number,\n year: number,\n selectionStart: Date | undefined,\n selectionEnd: Date | undefined,\n) {\n const {\n day: startDay,\n month: startMonth,\n year: startYear,\n } = selectionStart ? getDayMonthAndYearOfDate(selectionStart) : { day: undefined, month: undefined, year: undefined };\n const {\n day: endDay,\n month: endMonth,\n year: endYear,\n } = selectionEnd ? getDayMonthAndYearOfDate(selectionEnd) : { day: undefined, month: undefined, year: undefined };\n\n const toCheckNoTime = getDateFromDayMonthAndYear(day, month, year);\n\n const isStartDate = day === startDay && month === startMonth && year === startYear;\n const isEndDate = day === endDay && month === endMonth && year === endYear;\n\n let isInRange = false;\n if (\n startDay !== undefined &&\n startMonth !== undefined &&\n startYear !== undefined &&\n endDay !== undefined &&\n endMonth !== undefined &&\n endYear !== undefined\n ) {\n const selectionStartNoTime = getDateFromDayMonthAndYear(startDay, startMonth, startYear);\n const selectionEndNoTime = getDateFromDayMonthAndYear(endDay, endMonth, endYear);\n isInRange =\n toCheckNoTime.getTime() >= selectionStartNoTime.getTime() &&\n toCheckNoTime.getTime() <= selectionEndNoTime.getTime();\n }\n\n return { isStartDate, isInRange, isEndDate };\n}\n\nfunction checkDisabled(\n day: number,\n month: number,\n year: number,\n minDate: Date | null | undefined,\n maxDate: Date | null | undefined,\n): boolean {\n const toCheckNoTime = getDateFromDayMonthAndYear(day, month, year);\n\n if (minDate) {\n const { day: minDay, month: minMonth, year: minYear } = getDayMonthAndYearOfDate(minDate);\n if (toCheckNoTime < getDateFromDayMonthAndYear(minDay, minMonth, minYear)) return true;\n }\n\n if (maxDate) {\n const { day: maxDay, month: maxMonth, year: maxYear } = getDayMonthAndYearOfDate(maxDate);\n if (toCheckNoTime > getDateFromDayMonthAndYear(maxDay, maxMonth, maxYear)) return true;\n }\n\n return false;\n}\n\nfunction checkIsToday(day: number, month: number, year: number): boolean {\n const { day: currDay, month: currMonth, year: currYear } = getDayMonthAndYearOfDate(new Date());\n return day === currDay && month === currMonth && year === currYear;\n}\n\nexport default function DatePickerMonth({\n style,\n className = '',\n month = new Date().getMonth() + 1,\n year = new Date().getFullYear(),\n onSelect = () => null,\n selectionStart,\n selectionEnd,\n minDate = null,\n maxDate = null,\n onNavigateMonth,\n}: DatePickerMonthProps) {\n const locale = getLocale('-');\n const daysInMonth = getDaysInMonth(month, year);\n const startWeekDayOfMonth = getStartWeekDayOfMonth(month, year);\n\n const dayRefs = useRef<Record<number, HTMLDivElement | null>>({});\n const [focusedDay, setFocusedDay] = useState(() => getDefaultFocusedDay(month, year, selectionStart));\n\n // A day arrowed onto in an adjacent month, waiting for that month's grid to render so it\n // can be focused. `onNavigateMonth` only shifts `month`/`year` — the actual DOM focus has\n // to happen after this component re-renders with the new days, hence the effect below.\n const pendingFocusDayRef = useRef<number | null>(null);\n\n useEffect(() => {\n if (pendingFocusDayRef.current != null) {\n const day = pendingFocusDayRef.current;\n pendingFocusDayRef.current = null;\n setFocusedDay(day);\n dayRefs.current[day]?.focus();\n } else {\n // The displayed month changed some other way (header chevrons, month/year dropdowns) —\n // re-pick a sensible tab stop, but don't steal focus from whatever the user just used.\n setFocusedDay(getDefaultFocusedDay(month, year, selectionStart));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [month, year]);\n\n function handleDayKeyDown(event: React.KeyboardEvent<HTMLDivElement>, day: number) {\n let delta = 0;\n if (event.key === 'ArrowRight') delta = 1;\n else if (event.key === 'ArrowLeft') delta = -1;\n else if (event.key === 'ArrowDown') delta = 7;\n else if (event.key === 'ArrowUp') delta = -7;\n else return;\n\n event.preventDefault();\n const next = addDays(day, month, year, delta);\n\n if (next.month !== month || next.year !== year) {\n pendingFocusDayRef.current = next.day;\n onNavigateMonth?.(next.month > month || next.year > year ? 1 : -1);\n } else {\n setFocusedDay(next.day);\n dayRefs.current[next.day]?.focus();\n }\n }\n\n return (\n <div className={cx(styles.datePickerMonth, className)} style={style}>\n <div className={cx(styles.datePickerMonthContent)}>\n {getWeekDays(locale).map((weekDay, index) => (\n <div key={index}>{weekDay}</div>\n ))}\n {Array.from(Array(startWeekDayOfMonth - 1).keys()).map((index) => (\n <div key={index} className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)} />\n ))}\n {Array.from(Array(daysInMonth).keys()).map((index) => {\n const day = index + 1;\n const selectedRes = checkSelected(day, month, year, selectionStart, selectionEnd);\n const isDisabled = checkDisabled(day, month, year, minDate, maxDate);\n const isToday = checkIsToday(day, month, year);\n\n return (\n <InteractableDiv\n key={day}\n ref={(el) => {\n dayRefs.current[day] = el;\n }}\n tabIndex={day === focusedDay ? 0 : -1}\n onKeyDown={(event) => handleDayKeyDown(event, day)}\n onClick={() => (isDisabled ? null : onSelect(getDateFromDayMonthAndYear(day, month, year)))}\n className={cx(styles.datePickerMonthDay, styles.datePickerMonthItem, {\n [styles.datePickerMonthDaySelected]: selectedRes.isInRange,\n [styles.datePickerMonthDaySelectedStart]: selectedRes.isStartDate,\n [styles.datePickerMonthDaySelectedEnd]: selectedRes.isEndDate,\n [styles.datePickerMonthDayDisabled]: isDisabled,\n [styles.datePickerMonthDayToday]: isToday,\n })}\n >\n {day}\n </InteractableDiv>\n );\n })}\n {Array.from(Array(42 - (startWeekDayOfMonth + daysInMonth - 1)).keys()).map((index) => (\n <div key={index} className={cx(styles.datePickerMonthItem, styles.datePickerMonthPlaceholder)}>\n \n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"ydAmBA,SAAS,EAAqB,EAAe,EAAc,EAA0C,CACnG,GAAI,EAAgB,CAClB,IAAM,EAAM,EAAyB,CAAc,EACnD,GAAI,EAAI,QAAU,GAAS,EAAI,OAAS,EAAM,OAAO,EAAI,GAC3D,CACA,IAAM,EAAQ,EAAyB,IAAI,IAAM,EAEjD,OADI,EAAM,QAAU,GAAS,EAAM,OAAS,EAAa,EAAM,IACxD,CACT,CAEA,SAAS,EACP,EACA,EACA,EACA,EACA,EACA,CACA,GAAM,CACJ,IAAK,EACL,MAAO,EACP,KAAM,GACJ,EAAiB,EAAyB,CAAc,EAAI,CAAE,IAAK,IAAA,GAAW,MAAO,IAAA,GAAW,KAAM,IAAA,EAAU,EAC9G,CACJ,IAAK,EACL,MAAO,EACP,KAAM,GACJ,EAAe,EAAyB,CAAY,EAAI,CAAE,IAAK,IAAA,GAAW,MAAO,IAAA,GAAW,KAAM,IAAA,EAAU,EAE1G,EAAgB,EAA2B,EAAK,EAAO,CAAI,EAE3D,EAAc,IAAQ,GAAY,IAAU,GAAc,IAAS,EACnE,EAAY,IAAQ,GAAU,IAAU,GAAY,IAAS,EAE/D,EAAY,GAChB,GACE,IAAa,IAAA,IACb,IAAe,IAAA,IACf,IAAc,IAAA,IACd,IAAW,IAAA,IACX,IAAa,IAAA,IACb,IAAY,IAAA,GACZ,CACA,IAAM,EAAuB,EAA2B,EAAU,EAAY,CAAS,EACjF,EAAqB,EAA2B,EAAQ,EAAU,CAAO,EAC/E,EACE,EAAc,QAAQ,GAAK,EAAqB,QAAQ,GACxD,EAAc,QAAQ,GAAK,EAAmB,QAAQ,CAC1D,CAEA,MAAO,CAAE,cAAa,YAAW,WAAU,CAC7C,CAEA,SAAS,EACP,EACA,EACA,EACA,EACA,EACS,CACT,IAAM,EAAgB,EAA2B,EAAK,EAAO,CAAI,EAEjE,GAAI,EAAS,CACX,GAAM,CAAE,IAAK,EAAQ,MAAO,EAAU,KAAM,GAAY,EAAyB,CAAO,EACxF,GAAI,EAAgB,EAA2B,EAAQ,EAAU,CAAO,EAAG,MAAO,EACpF,CAEA,GAAI,EAAS,CACX,GAAM,CAAE,IAAK,EAAQ,MAAO,EAAU,KAAM,GAAY,EAAyB,CAAO,EACxF,GAAI,EAAgB,EAA2B,EAAQ,EAAU,CAAO,EAAG,MAAO,EACpF,CAEA,MAAO,EACT,CAEA,SAAS,EAAa,EAAa,EAAe,EAAuB,CACvE,GAAM,CAAE,IAAK,EAAS,MAAO,EAAW,KAAM,GAAa,EAAyB,IAAI,IAAM,EAC9F,OAAO,IAAQ,GAAW,IAAU,GAAa,IAAS,CAC5D,CAEA,SAAwB,EAAgB,CACtC,QACA,YAAY,GACZ,QAAQ,IAAI,KAAK,CAAA,CAAE,SAAS,EAAI,EAChC,OAAO,IAAI,KAAK,CAAA,CAAE,YAAY,EAC9B,eAAiB,KACjB,iBACA,eACA,UAAU,KACV,UAAU,KACV,mBACuB,CACvB,IAAM,EAAS,EAAU,GAAG,EACtB,EAAc,EAAe,EAAO,CAAI,EACxC,EAAsB,EAAuB,EAAO,CAAI,EAExD,EAAU,EAA8C,CAAC,CAAC,EAC1D,CAAC,EAAY,GAAiB,MAAe,EAAqB,EAAO,EAAM,CAAc,CAAC,EAK9F,EAAqB,EAAsB,IAAI,EAErD,MAAgB,CACd,GAAI,EAAmB,SAAW,KAAM,CACtC,IAAM,EAAM,EAAmB,QAC/B,EAAmB,QAAU,KAC7B,EAAc,CAAG,EACjB,EAAQ,QAAQ,EAAI,EAAE,MAAM,CAC9B,MAGE,EAAc,EAAqB,EAAO,EAAM,CAAc,CAAC,CAGnE,EAAG,CAAC,EAAO,CAAI,CAAC,EAEhB,SAAS,EAAiB,EAA4C,EAAa,CACjF,IAAI,EAAQ,EACZ,GAAI,EAAM,MAAQ,aAAc,EAAQ,OACnC,GAAI,EAAM,MAAQ,YAAa,EAAQ,QACvC,GAAI,EAAM,MAAQ,YAAa,EAAQ,OACvC,GAAI,EAAM,MAAQ,UAAW,EAAQ,QACrC,OAEL,EAAM,eAAe,EACrB,IAAM,EAAO,EAAQ,EAAK,EAAO,EAAM,CAAK,EAExC,EAAK,QAAU,GAAS,EAAK,OAAS,GACxC,EAAmB,QAAU,EAAK,IAClC,IAAkB,EAAK,MAAQ,GAAS,EAAK,KAAO,EAAO,EAAI,EAAE,IAEjE,EAAc,EAAK,GAAG,EACtB,EAAQ,QAAQ,EAAK,IAAI,EAAE,MAAM,EAErC,CAEA,OACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,gBAAiB,CAAS,EAAU,QAC5D,SAAA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,sBAAsB,EAAhD,SAAA,CACG,EAAY,CAAM,CAAC,CAAC,KAAK,EAAS,IACjC,EAAC,MAAD,CAAA,SAAkB,CAAa,EAArB,CAAqB,CAChC,EACA,MAAM,KAAK,MAAM,EAAsB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAK,GACtD,EAAC,MAAD,CAAiB,UAAW,EAAG,EAAO,oBAAqB,EAAO,0BAA0B,CAAI,EAAtF,CAAsF,CACjG,EACA,MAAM,KAAK,MAAM,CAAW,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAK,GAAU,CACpD,IAAM,EAAM,EAAQ,EACd,EAAc,EAAc,EAAK,EAAO,EAAM,EAAgB,CAAY,EAC1E,EAAa,EAAc,EAAK,EAAO,EAAM,EAAS,CAAO,EAC7D,EAAU,EAAa,EAAK,EAAO,CAAI,EAE7C,OACE,EAAC,EAAD,CAEE,IAAM,GAAO,CACX,EAAQ,QAAQ,GAAO,CACzB,EACA,SAAU,IAAQ,EAAa,EAAI,GACnC,UAAY,GAAU,EAAiB,EAAO,CAAG,EACjD,YAAgB,EAAa,KAAO,EAAS,EAA2B,EAAK,EAAO,CAAI,CAAC,EACzF,UAAW,EAAG,EAAO,mBAAoB,EAAO,oBAAqB,EAClE,EAAO,4BAA6B,EAAY,WAChD,EAAO,iCAAkC,EAAY,aACrD,EAAO,+BAAgC,EAAY,WACnD,EAAO,4BAA6B,GACpC,EAAO,yBAA0B,CACpC,CAAC,EAEA,SAAA,CACc,EAhBV,CAgBU,CAErB,CAAC,EACA,MAAM,KAAK,MAAM,IAAM,EAAsB,EAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAK,GAC3E,EAAC,MAAD,CAAiB,UAAW,EAAG,EAAO,oBAAqB,EAAO,0BAA0B,EAAG,SAAA,MAE1F,EAFK,CAEL,CACN,CACE,GACF,CAAA,CAET"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import t from"../button/button.mjs";import n from"../actionIcon/actionIcon.mjs";import{Align as r}from"../floatingMenu/floatingMenu.types.mjs";import i from"../floatingMenu/floatingMenu.mjs";import
|
|
1
|
+
import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import t from"../button/button.mjs";import n from"../actionIcon/actionIcon.mjs";import{Align as r}from"../floatingMenu/floatingMenu.types.mjs";import i from"../floatingMenu/floatingMenu.mjs";import ee from"../tooltip/tooltip.mjs";import a from"../input/input.mjs";import o from"../modal/modal.mjs";import{getLocale as s}from"../../services/localization.mjs";import{correctDateMaskValue as te,getDateFromDayMonthAndYear as ne,getDateString as c,getMonthName as re,getMonthNames as ie}from"./dateFunctions.mjs";import ae from"./components/datePickerMonth/datePickerMonth.mjs";import l from"../dropdown/dropdown.mjs";import u from"./datePicker.module.mjs";import{useEffect as d,useRef as f,useState as p}from"react";import m from"classnames";import{faChevronLeft as oe,faChevronRight as se}from"@fortawesome/free-solid-svg-icons";import{Fragment as ce,jsx as h,jsxs as g}from"react/jsx-runtime";import le from"@mona-health/react-input-mask";function _(_){let{className:ue=``,selected:v,onSelect:y=()=>null,formValidator:b=null,noInput:x=!1,noHeader:de=!1,isModal:S=!1,isInline:C=!1,onChange:fe=()=>null,minDate:w=null,maxDate:T=null,children:pe=null,showClearButton:me=!1,label:he=``,isValid:ge=!0,errorMessage:E=``,isRequired:_e=!1,startDate:D,endDate:O,style:k,classNames:A,styles:j,...M}=e(`DatePicker`,_),N=()=>b?b.value:v,P=N()??new Date,[F,I]=p(P.getMonth()+1),[L,R]=p(P.getFullYear()),[z,B]=p(!1),[V,H]=p(()=>N()?c(P):``),[ve,U]=p(!1),[ye,W]=p(!1),[,be]=p(0),[xe,Se]=p(v),G=f(b);if(xe!==v){Se(v);let e=v??new Date;I(e.getMonth()+1),R(e.getFullYear()),H(v?c(v):``)}d(()=>{if(G.current=b,!b)return;let e=()=>{let e=b.value;e?(I(e.getMonth()+1),R(e.getFullYear()),H(c(e))):H(``),be(e=>e+1)};return b.registerOnUpdateListener(e),()=>b.removeOnUpdateListener(e)},[b]);let Ce=()=>b?b.touched&&b.hasError():!ge||!!E,we=()=>!!(_e||b?.validators.find(e=>e.validatorId===`required`)),K=e=>{H(e?c(e):``),b&&b.set(e),fe(e)},q=e=>{K(e),y(e),B(!1)},J=e=>{I(t=>{let n=t+e;return n<1?(n=12,R(e=>e-1)):n>12&&(n=1,R(e=>e+1)),n})},Y=e=>{if(e.match(/\d{2}\.\d{2}\.\d{4}/gi)){let[t,n,r]=e.split(`.`),i=ne(Number(t),Number(n),Number(r));if(i&&i.toString()!==`Invalid Date`&&(!T||i<=T)&&(!w||i>=w))return i}return null},Te=({previousState:e,nextState:t})=>{if(!e||t.value===e.value)return t;let n=te(t.value,e.value,t.selection??null),r=Y(n.value);return r&&K(r),n},Ee=()=>{let e=400,t=new Date().getFullYear()-200;return w&&(t=w.getFullYear()),T&&(e=T.getFullYear()-t+1),Array.from(Array(e).keys()).map(e=>({key:e+t,label:e+t}))},X=N(),Z=Ce(),De=de?null:g(`div`,{className:m(u.datePickerHeader,A?.header),style:j?.header,children:[h(n,{icon:oe,onClick:()=>J(-1)}),h(`div`,{className:u.datePickerHeaderMonthAndYearContainer,children:g(`div`,{className:u.datePickerHeaderMonthAndYear,children:[h(l,{plainStyle:!0,scrollToSelected:!0,onChange:e=>I(e),className:m(u.datePickerHeaderMonth,A?.monthDropdown),style:j?.monthDropdown,value:re(s(`-`),L,F,1),items:ie().map((e,t)=>({key:t+1,label:e}))}),h(l,{plainStyle:!0,scrollToSelected:!0,useMatLabelStyle:!1,className:m(u.datePickerHeaderYear,A?.yearDropdown),style:j?.yearDropdown,onChange:e=>R(e),value:L,items:Ee()})]})}),h(n,{icon:se,onClick:()=>J(1)})]}),Q=g(ce,{children:[De,h(ae,{className:m(u.datePickerMonth,A?.calendar),style:j?.calendar,month:F,year:L,onSelect:q,selectionStart:D??X,selectionEnd:O??X,minDate:w,maxDate:T,onNavigateMonth:J}),me&&h(t,{onClick:()=>q(null),className:A?.clearButton,style:j?.clearButton,children:`Clear`}),pe]}),$=x?null:h(a,{autoComplete:`off`,className:A?.input,style:j?.input,readOnly:S,classNames:S?{input:u.datePickerModalInput}:void 0,label:`${he}${we()?` *`:``}`,value:V,onChange:e=>H(e),onClick:()=>B(!0),customInput:h(le,{mask:`99.99.9999`,maskPlaceholder:`_`,beforeMaskedStateChange:Te}),onBlur:()=>{G.current&&(G.current.touched=!0),U(!1),K(Y(V))},onFocus:()=>U(!0),onMouseEnter:()=>W(!0),onMouseLeave:()=>W(!1),isValid:!Z}),Oe=C?Q:S?h(o,{hideHeader:!0,isOpen:z,onClose:()=>B(!1),children:Q}):h(i,{isOpen:z,onOpenChange:e=>B(e),content:Q,align:r.Left,dontCloseOnChildClick:!0,children:$});return g(`div`,{...M,className:m(u.datePicker,ue,A?.root),style:{...k,...j?.root},children:[(S||C)&&$,Oe,h(ee,{variant:`error`,message:b?b.getCurrentErrorMessage():E||``,isVisible:Z&&(ve||ye)})]})}export{_ as default};
|
|
2
2
|
//# sourceMappingURL=datePicker.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datePicker.mjs","names":[],"sources":["../../../../package/common/datePicker/datePicker.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport Input from '../input';\nimport { useComponentDefaults } from '../configProvider';\nimport DatePickerMonth from './components/datePickerMonth';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\nimport { getLocale } from 'services/localization';\nimport ActionIcon from '../actionIcon';\nimport Modal from '../modal';\nimport FloatingMenu from '../floatingMenu';\nimport Dropdown from '../dropdown';\nimport { Align } from '../floatingMenu/floatingMenu.types';\nimport InputMask, { InputState, BeforeMaskedStateChangeStates } from '@mona-health/react-input-mask';\nimport {\n getDateFromDayMonthAndYear,\n getMonthName,\n getMonthNames,\n getDateString,\n correctDateMaskValue,\n} from './dateFunctions';\nimport Button from '../button';\nimport Tooltip from '../tooltip';\nimport type { FormValidator } from 'services/formValidation';\n\nimport styles from './datePicker.module.pcss';\n\nexport interface DatePickerProps {\n className?: string;\n selected?: Date;\n onSelect?: (date: Date | null) => void;\n formValidator?: FormValidator | null;\n noInput?: boolean;\n noHeader?: boolean;\n isModal?: boolean;\n isInline?: boolean;\n onChange?: (date: Date | null) => void;\n minDate?: Date | null;\n maxDate?: Date | null;\n children?: React.ReactNode;\n showClearButton?: boolean;\n label?: string;\n isValid?: boolean;\n errorMessage?: string;\n isRequired?: boolean;\n startDate?: Date;\n endDate?: Date;\n}\n\nexport default function DatePicker(props: DatePickerProps) {\n const {\n className = '',\n selected,\n onSelect = () => null,\n formValidator = null,\n noInput = false,\n noHeader = false,\n isModal = false,\n isInline = false,\n onChange = () => null,\n minDate = null,\n maxDate = null,\n children = null,\n showClearButton = false,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n startDate,\n endDate,\n } = useComponentDefaults('DatePicker', props);\n const getCurrValue = (): Date | undefined => (formValidator ? (formValidator.value as Date) : selected);\n\n const initialDate = getCurrValue() ?? new Date();\n\n const [currentMonth, setCurrentMonth] = useState(initialDate.getMonth() + 1);\n const [currentYear, setCurrentYear] = useState(initialDate.getFullYear());\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [currentDateString, setCurrentDateString] = useState(() => (getCurrValue() ? getDateString(initialDate) : ''));\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n const [prevSelected, setPrevSelected] = useState(selected);\n\n const fvRef = useRef(formValidator);\n\n // Sync navigation view when `selected` prop changes externally\n if (prevSelected !== selected) {\n setPrevSelected(selected);\n const d = selected ?? new Date();\n setCurrentMonth(d.getMonth() + 1);\n setCurrentYear(d.getFullYear());\n setCurrentDateString(selected ? getDateString(selected) : '');\n }\n\n // Subscribe to formValidator updates (external system → setState in callback)\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n const val = formValidator.value as Date | undefined;\n if (val) {\n setCurrentMonth(val.getMonth() + 1);\n setCurrentYear(val.getFullYear());\n setCurrentDateString(getDateString(val));\n } else {\n setCurrentDateString('');\n }\n forceUpdate((n: number) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean => {\n return formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n };\n\n const computedIsRequired = (): boolean => {\n return !!(\n isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required')\n );\n };\n\n const handleChange = (date: Date | null) => {\n setCurrentDateString(date ? getDateString(date) : '');\n if (formValidator) formValidator.set(date);\n onChange(date);\n };\n\n const handleSelect = (date: Date | null) => {\n handleChange(date);\n onSelect(date);\n setIsPickerOpen(false);\n };\n\n const changeMonth = (delta: number) => {\n setCurrentMonth((prev) => {\n let next = prev + delta;\n if (next < 1) {\n next = 12;\n setCurrentYear((y) => y - 1);\n } else if (next > 12) {\n next = 1;\n setCurrentYear((y) => y + 1);\n }\n return next;\n });\n };\n\n const tryParseDateString = (dateString: string): Date | null => {\n if (dateString.match(/\\d{2}\\.\\d{2}\\.\\d{4}/gi)) {\n const [day, month, year] = dateString.split('.');\n const parsedDate = getDateFromDayMonthAndYear(Number(day), Number(month), Number(year));\n if (parsedDate && parsedDate.toString() !== 'Invalid Date') {\n const isSmallerThanMaxDate = !maxDate || parsedDate <= maxDate;\n const isBiggerThanMinDate = !minDate || parsedDate >= minDate;\n if (isSmallerThanMaxDate && isBiggerThanMinDate) return parsedDate;\n }\n }\n return null;\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): InputState => {\n // previousState is only supplied on user-driven change events; on mount/focus/blur\n // there is nothing to auto-correct, so the next state passes through unchanged.\n if (!previousState || nextState.value === previousState.value) return nextState;\n\n const corrected = correctDateMaskValue(nextState.value, previousState.value, nextState.selection ?? null);\n\n const parsedDate = tryParseDateString(corrected.value);\n if (parsedDate) handleChange(parsedDate);\n\n return corrected;\n };\n\n const getYearDropdownOptions = () => {\n let length = 400;\n let zeroOffset = new Date().getFullYear() - 200;\n if (minDate) zeroOffset = minDate.getFullYear();\n if (maxDate) length = maxDate.getFullYear() - zeroOffset + 1;\n return Array.from(Array(length).keys()).map((i) => ({ key: i + zeroOffset, label: i + zeroOffset }));\n };\n\n const currValue = getCurrValue();\n const hasErr = hasError();\n\n const header = noHeader ? null : (\n <div className={styles.datePickerHeader}>\n <ActionIcon icon={faChevronLeft} onClick={() => changeMonth(-1)} />\n <div className={styles.datePickerHeaderMonthAndYearContainer}>\n <div className={styles.datePickerHeaderMonthAndYear}>\n <Dropdown\n plainStyle\n scrollToSelected\n onChange={(v) => setCurrentMonth(v as number)}\n className={styles.datePickerHeaderMonth}\n value={getMonthName(getLocale('-'), currentYear, currentMonth, 1)}\n items={getMonthNames().map((month, index) => ({ key: index + 1, label: month }))}\n />\n <Dropdown\n plainStyle\n scrollToSelected\n useMatLabelStyle={false}\n className={styles.datePickerHeaderYear}\n onChange={(v) => setCurrentYear(v as number)}\n value={currentYear}\n items={getYearDropdownOptions()}\n />\n </div>\n </div>\n <ActionIcon icon={faChevronRight} onClick={() => changeMonth(1)} />\n </div>\n );\n\n const pickerContent = (\n <>\n {header}\n <DatePickerMonth\n className={styles.datePickerMonth}\n month={currentMonth}\n year={currentYear}\n onSelect={handleSelect}\n selectionStart={startDate ?? currValue}\n selectionEnd={endDate ?? currValue}\n minDate={minDate}\n maxDate={maxDate}\n onNavigateMonth={changeMonth}\n />\n {showClearButton && <Button onClick={() => handleSelect(null)}>Clear</Button>}\n {children}\n </>\n );\n\n const input = noInput ? null : (\n <Input\n autoComplete='off'\n readOnly={isModal}\n classNames={isModal ? { input: styles.datePickerModalInput } : undefined}\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentDateString}\n onChange={(v) => setCurrentDateString(v as string)}\n onClick={() => setIsPickerOpen(true)}\n customInput={\n <InputMask mask='99.99.9999' maskPlaceholder='_' beforeMaskedStateChange={beforeMaskedStateChange} />\n }\n onBlur={() => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n handleChange(tryParseDateString(currentDateString));\n }}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n isValid={!hasErr}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <FloatingMenu\n isOpen={isPickerOpen}\n onOpenChange={(open: boolean) => setIsPickerOpen(open)}\n content={pickerContent}\n align={Align.Left}\n dontCloseOnChildClick\n >\n {input}\n </FloatingMenu>\n );\n })();\n\n return (\n <div className={cx(styles.datePicker, className)}>\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant='error'\n message={formValidator ? formValidator.getCurrentErrorMessage() : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n"],"mappings":"2/BAgDA,SAAwB,EAAW,EAAwB,CACzD,GAAM,CACJ,aAAY,GACZ,WACA,eAAiB,KACjB,gBAAgB,KAChB,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,GACX,gBAAiB,KACjB,UAAU,KACV,UAAU,KACV,YAAW,KACX,mBAAkB,GAClB,SAAQ,GACR,UAAU,GACV,eAAe,GACf,aAAa,GACb,YACA,WACE,EAAqB,aAAc,CAAK,EACtC,MAAwC,EAAiB,EAAc,MAAiB,EAExF,EAAc,EAAa,GAAK,IAAI,KAEpC,CAAC,EAAc,GAAmB,EAAS,EAAY,SAAS,EAAI,CAAC,EACrE,CAAC,EAAa,GAAkB,EAAS,EAAY,YAAY,CAAC,EAClE,CAAC,EAAc,GAAmB,EAAS,EAAK,EAChD,CAAC,EAAmB,GAAwB,MAAgB,EAAa,EAAI,EAAc,CAAW,EAAI,EAAG,EAC7G,CAAC,GAAW,GAAgB,EAAS,EAAK,EAC1C,CAAC,GAAW,GAAgB,EAAS,EAAK,EAC1C,EAAG,IAAe,EAAS,CAAC,EAC5B,CAAC,GAAc,IAAmB,EAAS,CAAQ,EAEnD,EAAQ,EAAO,CAAa,EAGlC,GAAI,KAAiB,EAAU,CAC7B,GAAgB,CAAQ,EACxB,IAAM,EAAI,GAAY,IAAI,KAC1B,EAAgB,EAAE,SAAS,EAAI,CAAC,EAChC,EAAe,EAAE,YAAY,CAAC,EAC9B,EAAqB,EAAW,EAAc,CAAQ,EAAI,EAAE,CAC9D,CAGA,MAAgB,CAEd,GADA,EAAM,QAAU,EACZ,CAAC,EAAe,OACpB,IAAM,MAAiB,CACrB,IAAM,EAAM,EAAc,MACtB,GACF,EAAgB,EAAI,SAAS,EAAI,CAAC,EAClC,EAAe,EAAI,YAAY,CAAC,EAChC,EAAqB,EAAc,CAAG,CAAC,GAEvC,EAAqB,EAAE,EAEzB,GAAa,GAAc,EAAI,CAAC,CAClC,EAEA,OADA,EAAc,yBAAyB,CAAQ,MAClC,EAAc,uBAAuB,CAAQ,CAC5D,EAAG,CAAC,CAAa,CAAC,EAElB,IAAM,OACG,EAAgB,EAAc,SAAW,EAAc,SAAS,EAAI,CAAC,GAAW,CAAC,CAAC,EAGrF,OACG,CAAC,EACN,GAAc,GAAe,WAAW,KAAM,GAAO,EAA+B,cAAgB,UAAU,GAI5G,EAAgB,GAAsB,CAC1C,EAAqB,EAAO,EAAc,CAAI,EAAI,EAAE,EAChD,GAAe,EAAc,IAAI,CAAI,EACzC,GAAS,CAAI,CACf,EAEM,EAAgB,GAAsB,CAC1C,EAAa,CAAI,EACjB,EAAS,CAAI,EACb,EAAgB,EAAK,CACvB,EAEM,EAAe,GAAkB,CACrC,EAAiB,GAAS,CACxB,IAAI,EAAO,EAAO,EAQlB,OAPI,EAAO,GACT,EAAO,GACP,EAAgB,GAAM,EAAI,CAAC,GAClB,EAAO,KAChB,EAAO,EACP,EAAgB,GAAM,EAAI,CAAC,GAEtB,CACT,CAAC,CACH,EAEM,EAAsB,GAAoC,CAC9D,GAAI,EAAW,MAAM,uBAAuB,EAAG,CAC7C,GAAM,CAAC,EAAK,EAAO,GAAQ,EAAW,MAAM,GAAG,EACzC,EAAa,GAA2B,OAAO,CAAG,EAAG,OAAO,CAAK,EAAG,OAAO,CAAI,CAAC,EACtF,GAAI,GAAc,EAAW,SAAS,IAAM,iBACb,CAAC,GAAW,GAAc,KAC3B,CAAC,GAAW,GAAc,GACL,OAAO,CAE5D,CACA,OAAO,IACT,EAEM,IAA2B,CAAE,gBAAe,eAA2D,CAG3G,GAAI,CAAC,GAAiB,EAAU,QAAU,EAAc,MAAO,OAAO,EAEtE,IAAM,EAAY,GAAqB,EAAU,MAAO,EAAc,MAAO,EAAU,WAAa,IAAI,EAElG,EAAa,EAAmB,EAAU,KAAK,EAGrD,OAFI,GAAY,EAAa,CAAU,EAEhC,CACT,EAEM,OAA+B,CACnC,IAAI,EAAS,IACT,EAAa,IAAI,KAAK,CAAA,CAAE,YAAY,EAAI,IAG5C,OAFI,IAAS,EAAa,EAAQ,YAAY,GAC1C,IAAS,EAAS,EAAQ,YAAY,EAAI,EAAa,GACpD,MAAM,KAAK,MAAM,CAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAK,IAAO,CAAE,IAAK,EAAI,EAAY,MAAO,EAAI,CAAW,EAAE,CACrG,EAEM,EAAY,EAAa,EACzB,EAAS,GAAS,EAElB,GAAS,EAAW,KACxB,EAAC,MAAD,CAAK,UAAW,EAAO,iBAAvB,SAAA,CACE,EAAC,EAAD,CAAY,KAAM,GAAe,YAAe,EAAY,EAAE,CAAI,CAAA,EAClE,EAAC,MAAD,CAAK,UAAW,EAAO,sCACrB,SAAA,EAAC,MAAD,CAAK,UAAW,EAAO,6BAAvB,SAAA,CACE,EAAC,EAAD,CACE,WAAA,GACA,iBAAA,GACA,SAAW,GAAM,EAAgB,CAAW,EAC5C,UAAW,EAAO,sBAClB,MAAO,GAAa,EAAU,GAAG,EAAG,EAAa,EAAc,CAAC,EAChE,MAAO,GAAc,CAAC,CAAC,KAAK,EAAO,KAAW,CAAE,IAAK,EAAQ,EAAG,MAAO,CAAM,EAAE,CAChF,CAAA,EACD,EAAC,EAAD,CACE,WAAA,GACA,iBAAA,GACA,iBAAkB,GAClB,UAAW,EAAO,qBAClB,SAAW,GAAM,EAAe,CAAW,EAC3C,MAAO,EACP,MAAO,GAAuB,CAC/B,CAAA,CACE,GACF,CAAA,EACL,EAAC,EAAD,CAAY,KAAM,GAAgB,YAAe,EAAY,CAAC,CAAI,CAAA,CAC/D,IAGD,EACJ,EAAA,GAAA,CAAA,SAAA,CACG,GACD,EAAC,GAAD,CACE,UAAW,EAAO,gBAClB,MAAO,EACP,KAAM,EACN,SAAU,EACV,eAAgB,GAAa,EAC7B,aAAc,GAAW,EAChB,UACA,UACT,gBAAiB,CAClB,CAAA,EACA,IAAmB,EAAC,EAAD,CAAQ,YAAe,EAAa,IAAI,EAAG,SAAA,OAAa,CAAA,EAC3E,EACD,CAAA,CAAA,EAGE,EAAQ,EAAU,KACtB,EAAC,EAAD,CACE,aAAa,MACb,SAAU,EACV,WAAY,EAAU,CAAE,MAAO,EAAO,oBAAqB,EAAI,IAAA,GAC/D,MAAO,GAAG,KAAQ,GAAmB,EAAI,KAAO,KAChD,MAAO,EACP,SAAW,GAAM,EAAqB,CAAW,EACjD,YAAe,EAAgB,EAAI,EACnC,YACE,EAAC,GAAD,CAAW,KAAK,aAAa,gBAAgB,IAA6B,0BAA0B,CAAA,EAEtG,WAAc,CACR,EAAM,UAAS,EAAM,QAAQ,QAAU,IAC3C,EAAa,EAAK,EAClB,EAAa,EAAmB,CAAiB,CAAC,CACpD,EACA,YAAe,EAAa,EAAI,EAChC,iBAAoB,EAAa,EAAI,EACrC,iBAAoB,EAAa,EAAK,EACtC,QAAS,CAAC,CACX,CAAA,EAGG,GACA,EAAiB,EACjB,EAEA,EAAC,EAAD,CAAO,WAAA,GAAW,OAAQ,EAAc,YAAe,EAAgB,EAAK,EACzE,SAAA,CACI,CAAA,EAIT,EAAC,EAAD,CACE,OAAQ,EACR,aAAe,GAAkB,EAAgB,CAAI,EACrD,QAAS,EACT,MAAO,EAAM,KACb,sBAAA,GAEC,SAAA,CACW,CAAA,EAIlB,OACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,WAAY,EAAS,EAA/C,SAAA,EACI,GAAW,IAAa,EACzB,GACD,EAAC,EAAD,CACE,QAAQ,QACR,QAAS,EAAgB,EAAc,uBAAuB,EAAI,GAAgB,GAClF,UAAW,IAAW,IAAa,GACpC,CAAA,CACE,GAET"}
|
|
1
|
+
{"version":3,"file":"datePicker.mjs","names":[],"sources":["../../../../package/common/datePicker/datePicker.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport Input from '../input';\nimport { useComponentDefaults } from '../configProvider';\nimport DatePickerMonth from './components/datePickerMonth';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\nimport { getLocale } from 'services/localization';\nimport ActionIcon from '../actionIcon';\nimport Modal from '../modal';\nimport FloatingMenu from '../floatingMenu';\nimport Dropdown from '../dropdown';\nimport { Align } from '../floatingMenu/floatingMenu.types';\nimport InputMask, { InputState, BeforeMaskedStateChangeStates } from '@mona-health/react-input-mask';\nimport {\n getDateFromDayMonthAndYear,\n getMonthName,\n getMonthNames,\n getDateString,\n correctDateMaskValue,\n} from './dateFunctions';\nimport Button from '../button';\nimport Tooltip from '../tooltip';\nimport type { DatePickerProps } from './datePicker.types';\n\nimport styles from './datePicker.module.pcss';\n\nexport default function DatePicker(props: DatePickerProps) {\n const {\n className = '',\n selected,\n onSelect = () => null,\n formValidator = null,\n noInput = false,\n noHeader = false,\n isModal = false,\n isInline = false,\n onChange = () => null,\n minDate = null,\n maxDate = null,\n children = null,\n showClearButton = false,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n startDate,\n endDate,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('DatePicker', props);\n const getCurrValue = (): Date | undefined => (formValidator ? (formValidator.value as Date) : selected);\n\n const initialDate = getCurrValue() ?? new Date();\n\n const [currentMonth, setCurrentMonth] = useState(initialDate.getMonth() + 1);\n const [currentYear, setCurrentYear] = useState(initialDate.getFullYear());\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [currentDateString, setCurrentDateString] = useState(() => (getCurrValue() ? getDateString(initialDate) : ''));\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n const [prevSelected, setPrevSelected] = useState(selected);\n\n const fvRef = useRef(formValidator);\n\n // Sync navigation view when `selected` prop changes externally\n if (prevSelected !== selected) {\n setPrevSelected(selected);\n const d = selected ?? new Date();\n setCurrentMonth(d.getMonth() + 1);\n setCurrentYear(d.getFullYear());\n setCurrentDateString(selected ? getDateString(selected) : '');\n }\n\n // Subscribe to formValidator updates (external system → setState in callback)\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n const val = formValidator.value as Date | undefined;\n if (val) {\n setCurrentMonth(val.getMonth() + 1);\n setCurrentYear(val.getFullYear());\n setCurrentDateString(getDateString(val));\n } else {\n setCurrentDateString('');\n }\n forceUpdate((n: number) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean => {\n return formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n };\n\n const computedIsRequired = (): boolean => {\n return !!(\n isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required')\n );\n };\n\n const handleChange = (date: Date | null) => {\n setCurrentDateString(date ? getDateString(date) : '');\n if (formValidator) formValidator.set(date);\n onChange(date);\n };\n\n const handleSelect = (date: Date | null) => {\n handleChange(date);\n onSelect(date);\n setIsPickerOpen(false);\n };\n\n const changeMonth = (delta: number) => {\n setCurrentMonth((prev) => {\n let next = prev + delta;\n if (next < 1) {\n next = 12;\n setCurrentYear((y) => y - 1);\n } else if (next > 12) {\n next = 1;\n setCurrentYear((y) => y + 1);\n }\n return next;\n });\n };\n\n const tryParseDateString = (dateString: string): Date | null => {\n if (dateString.match(/\\d{2}\\.\\d{2}\\.\\d{4}/gi)) {\n const [day, month, year] = dateString.split('.');\n const parsedDate = getDateFromDayMonthAndYear(Number(day), Number(month), Number(year));\n if (parsedDate && parsedDate.toString() !== 'Invalid Date') {\n const isSmallerThanMaxDate = !maxDate || parsedDate <= maxDate;\n const isBiggerThanMinDate = !minDate || parsedDate >= minDate;\n if (isSmallerThanMaxDate && isBiggerThanMinDate) return parsedDate;\n }\n }\n return null;\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): InputState => {\n // previousState is only supplied on user-driven change events; on mount/focus/blur\n // there is nothing to auto-correct, so the next state passes through unchanged.\n if (!previousState || nextState.value === previousState.value) return nextState;\n\n const corrected = correctDateMaskValue(nextState.value, previousState.value, nextState.selection ?? null);\n\n const parsedDate = tryParseDateString(corrected.value);\n if (parsedDate) handleChange(parsedDate);\n\n return corrected;\n };\n\n const getYearDropdownOptions = () => {\n let length = 400;\n let zeroOffset = new Date().getFullYear() - 200;\n if (minDate) zeroOffset = minDate.getFullYear();\n if (maxDate) length = maxDate.getFullYear() - zeroOffset + 1;\n return Array.from(Array(length).keys()).map((i) => ({ key: i + zeroOffset, label: i + zeroOffset }));\n };\n\n const currValue = getCurrValue();\n const hasErr = hasError();\n\n const header = noHeader ? null : (\n <div className={cx(styles.datePickerHeader, classNames?.header)} style={slotStyles?.header}>\n <ActionIcon icon={faChevronLeft} onClick={() => changeMonth(-1)} />\n <div className={styles.datePickerHeaderMonthAndYearContainer}>\n <div className={styles.datePickerHeaderMonthAndYear}>\n <Dropdown\n plainStyle\n scrollToSelected\n onChange={(v) => setCurrentMonth(v as number)}\n className={cx(styles.datePickerHeaderMonth, classNames?.monthDropdown)}\n style={slotStyles?.monthDropdown}\n value={getMonthName(getLocale('-'), currentYear, currentMonth, 1)}\n items={getMonthNames().map((month, index) => ({ key: index + 1, label: month }))}\n />\n <Dropdown\n plainStyle\n scrollToSelected\n useMatLabelStyle={false}\n className={cx(styles.datePickerHeaderYear, classNames?.yearDropdown)}\n style={slotStyles?.yearDropdown}\n onChange={(v) => setCurrentYear(v as number)}\n value={currentYear}\n items={getYearDropdownOptions()}\n />\n </div>\n </div>\n <ActionIcon icon={faChevronRight} onClick={() => changeMonth(1)} />\n </div>\n );\n\n const pickerContent = (\n <>\n {header}\n <DatePickerMonth\n className={cx(styles.datePickerMonth, classNames?.calendar)}\n style={slotStyles?.calendar}\n month={currentMonth}\n year={currentYear}\n onSelect={handleSelect}\n selectionStart={startDate ?? currValue}\n selectionEnd={endDate ?? currValue}\n minDate={minDate}\n maxDate={maxDate}\n onNavigateMonth={changeMonth}\n />\n {showClearButton && (\n <Button onClick={() => handleSelect(null)} className={classNames?.clearButton} style={slotStyles?.clearButton}>\n Clear\n </Button>\n )}\n {children}\n </>\n );\n\n const input = noInput ? null : (\n <Input\n autoComplete='off'\n className={classNames?.input}\n style={slotStyles?.input}\n readOnly={isModal}\n classNames={isModal ? { input: styles.datePickerModalInput } : undefined}\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentDateString}\n onChange={(v) => setCurrentDateString(v as string)}\n onClick={() => setIsPickerOpen(true)}\n customInput={\n <InputMask mask='99.99.9999' maskPlaceholder='_' beforeMaskedStateChange={beforeMaskedStateChange} />\n }\n onBlur={() => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n handleChange(tryParseDateString(currentDateString));\n }}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n isValid={!hasErr}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <FloatingMenu\n isOpen={isPickerOpen}\n onOpenChange={(open: boolean) => setIsPickerOpen(open)}\n content={pickerContent}\n align={Align.Left}\n dontCloseOnChildClick\n >\n {input}\n </FloatingMenu>\n );\n })();\n\n return (\n <div\n {...rest}\n className={cx(styles.datePicker, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant='error'\n message={formValidator ? formValidator.getCurrentErrorMessage() : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"./drawer.module.mjs";import{useEffect as t,useRef as n}from"react";import r from"classnames";import{jsx as i}from"react/jsx-runtime";function a({className:a,isOpen:o=!1,closedWidth:s,openedWidth:c,children:l}){let
|
|
1
|
+
import e from"./drawer.module.mjs";import{useEffect as t,useRef as n}from"react";import r from"classnames";import{jsx as i}from"react/jsx-runtime";function a({className:a,isOpen:o=!1,closedWidth:s,openedWidth:c,children:l,style:u,classNames:d,styles:f,...p}){let m=n(null),h=n(null);return t(()=>{let e=new ResizeObserver(()=>{m.current&&h.current&&m.current.style.setProperty(`--drawer-content-width`,`${h.current.scrollWidth}px`)});return h.current&&e.observe(h.current),()=>e.disconnect()},[]),i(`div`,{...p,ref:m,className:r(e.drawer,o&&e.drawerOpen,a,d?.root),style:{...s!==void 0&&{"--drawer-closed-width":s},...c!==void 0&&{"--drawer-opened-width":c},...u,...f?.root},children:i(`div`,{ref:h,className:r(e.drawerContent,d?.content),style:f?.content,children:i(`div`,{className:r(e.drawerContentInner,d?.inner),style:f?.inner,children:l})})})}export{a as default};
|
|
2
2
|
//# sourceMappingURL=drawer.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawer.mjs","names":[],"sources":["../../../../package/common/drawer/drawer.tsx"],"sourcesContent":["import type { ReactElement, CSSProperties } from 'react';\nimport { useRef, useEffect } from 'react';\nimport { DrawerProps } from './drawer.types';\nimport cx from 'classnames';\n\nimport styles from './drawer.module.pcss';\n\nfunction Drawer({
|
|
1
|
+
{"version":3,"file":"drawer.mjs","names":[],"sources":["../../../../package/common/drawer/drawer.tsx"],"sourcesContent":["import type { ReactElement, CSSProperties } from 'react';\nimport { useRef, useEffect } from 'react';\nimport { DrawerProps } from './drawer.types';\nimport cx from 'classnames';\n\nimport styles from './drawer.module.pcss';\n\nfunction Drawer({\n className,\n isOpen = false,\n closedWidth,\n openedWidth,\n children,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: DrawerProps): ReactElement {\n const containerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const observer = new ResizeObserver(() => {\n if (containerRef.current && contentRef.current) {\n containerRef.current.style.setProperty('--drawer-content-width', `${contentRef.current.scrollWidth}px`);\n }\n });\n if (contentRef.current) observer.observe(contentRef.current);\n return () => observer.disconnect();\n }, []);\n\n return (\n <div\n {...rest}\n ref={containerRef}\n className={cx(styles.drawer, isOpen && styles.drawerOpen, className, classNames?.root)}\n style={\n {\n ...(closedWidth !== undefined && { '--drawer-closed-width': closedWidth }),\n ...(openedWidth !== undefined && { '--drawer-opened-width': openedWidth }),\n ...style,\n ...slotStyles?.root,\n } as CSSProperties\n }\n >\n <div ref={contentRef} className={cx(styles.drawerContent, classNames?.content)} style={slotStyles?.content}>\n <div className={cx(styles.drawerContentInner, classNames?.inner)} style={slotStyles?.inner}>\n {children}\n </div>\n </div>\n </div>\n );\n}\n\nexport default Drawer;\n"],"mappings":"mJAOA,SAAS,EAAO,CACd,YACA,SAAS,GACT,cACA,cACA,WACA,QACA,aACA,OAAQ,EACR,GAAG,GACyB,CAC5B,IAAM,EAAe,EAAuB,IAAI,EAC1C,EAAa,EAAuB,IAAI,EAY9C,OAVA,MAAgB,CACd,IAAM,EAAW,IAAI,mBAAqB,CACpC,EAAa,SAAW,EAAW,SACrC,EAAa,QAAQ,MAAM,YAAY,yBAA0B,GAAG,EAAW,QAAQ,YAAY,GAAG,CAE1G,CAAC,EAED,OADI,EAAW,SAAS,EAAS,QAAQ,EAAW,OAAO,MAC9C,EAAS,WAAW,CACnC,EAAG,CAAC,CAAC,EAGH,EAAC,MAAD,CACE,GAAI,EACJ,IAAK,EACL,UAAW,EAAG,EAAO,OAAQ,GAAU,EAAO,WAAY,EAAW,GAAY,IAAI,EACrF,MACE,CACE,GAAI,IAAgB,IAAA,IAAa,CAAE,wBAAyB,CAAY,EACxE,GAAI,IAAgB,IAAA,IAAa,CAAE,wBAAyB,CAAY,EACxE,GAAG,EACH,GAAG,GAAY,IACjB,EAGF,SAAA,EAAC,MAAD,CAAK,IAAK,EAAY,UAAW,EAAG,EAAO,cAAe,GAAY,OAAO,EAAG,MAAO,GAAY,QACjG,SAAA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,mBAAoB,GAAY,KAAK,EAAG,MAAO,GAAY,MAClF,UACE,CAAA,CACF,CAAA,CACF,CAAA,CAET"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{usePresentationDefault as t}from"../configProvider/usePresentationDefault.mjs";import n from"../bodyEnd/bodyEnd.mjs";import r from"../styles/sheet.module.mjs";import ee from"../sheetBackdrop/sheetBackdrop.mjs";import{useFloatingPosition as i}from"../floatingMenu/useFloatingPosition.mjs";import{Presentation as a}from"../floatingMenu/floatingMenu.types.mjs";import o from"../hooks/useSheet.mjs";import{useOverlay as s}from"../hooks/useOverlay.mjs";import c from"../tooltip/tooltip.mjs";import te from"../infiniteBlock/infiniteBlock.mjs";import l from"./dropdown.module.mjs";import{useEffect as u,useLayoutEffect as ne,useRef as d,useState as f}from"react";import p from"classnames";import{FontAwesomeIcon as
|
|
1
|
+
import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{usePresentationDefault as t}from"../configProvider/usePresentationDefault.mjs";import n from"../bodyEnd/bodyEnd.mjs";import r from"../styles/sheet.module.mjs";import ee from"../sheetBackdrop/sheetBackdrop.mjs";import{useFloatingPosition as i}from"../floatingMenu/useFloatingPosition.mjs";import{Presentation as a}from"../floatingMenu/floatingMenu.types.mjs";import o from"../hooks/useSheet.mjs";import{useOverlay as s}from"../hooks/useOverlay.mjs";import c from"../tooltip/tooltip.mjs";import te from"../infiniteBlock/infiniteBlock.mjs";import l from"./dropdown.module.mjs";import{useEffect as u,useLayoutEffect as ne,useRef as d,useState as f}from"react";import p from"classnames";import{FontAwesomeIcon as re}from"@fortawesome/react-fontawesome";import{faChevronDown as ie}from"@fortawesome/free-solid-svg-icons";import{jsx as m,jsxs as h}from"react/jsx-runtime";import ae from"downshift";function g(g){let{errorMessage:_=``,className:v=``,style:oe,label:y=``,value:se=``,isValid:ce=!0,tabIndex:b=0,isRequired:le=!1,customProps:x={},isRow:ue=!1,disabled:S=!1,readOnly:C=!1,onScroll:de=()=>Promise.resolve(),onClick:w,onChange:T,onFocus:fe=null,onBlur:pe=null,onMouseEnter:me=null,onMouseLeave:he=null,dropdownLabel:ge,isDropdownListWider:E=!1,formValidator:D=null,classNames:O,styles:k,items:A=[],useMatLabelStyle:j=!0,alwaysFloatLabel:M=!1,placeholder:N=``,plainStyle:P=!1,scrollToSelected:F=!1,presentation:I,reactRef:L,..._e}=e(`Dropdown`,g),[R,z]=f(!1),[ve,B]=f(!1),[,ye]=f(0),V=d(D),H=d(null),U=d(null),[W,be]=f(!1),xe=t(),Se=I??xe??a.Default,{isSheet:G,sheetStyle:Ce}=o(Se);ne(()=>{let e=H.current,t=U.current;if(!W||G||!e||!t)return;let{width:n}=e.getBoundingClientRect(),{fontSize:r}=window.getComputedStyle(e);t.style.width=`${n}px`,t.style.fontSize=r},[W,G]),i({isOpen:W&&!G,triggerRef:H,anchorRef:U,panelRef:U,flipClassName:l.dropdownInputListAnimFlip}),s({isActive:W,containerRef:U,trapFocus:!1,lockScroll:G}),u(()=>{if(V.current=D,!V.current)return;V.current.label=y??``,V.current.validate();let e=()=>ye(e=>e+1);return V.current.registerOnUpdateListener(e),()=>V.current?.removeOnUpdateListener(e)},[D,y]);let we=e=>{B(!0),me?.(e)},Te=e=>{B(!1),he?.(e)},Ee=e=>{z(!0),fe?.(e)},De=e=>{V.current&&(V.current.touched=!0),z(!1),pe?.(e)},Oe=()=>D?D.touched&&D.hasError():!ce||!!_,K=()=>!!(le||D?.validators.find(e=>e.validatorId===`required`)),ke=e=>{D?(D.set(e),T?.(D.value,x)):T?.(e,x)},q=ge,J=D?D.value:se,Y=Oe();A.forEach(e=>{e.key===J&&(q=e.label)});let X=q||J,Z=X==null||typeof X==`string`&&X.trim()===``,Q=K()?m(`span`,{className:l.requiredMark,children:`*`}):null,Ae=y&&K()?`${y} *`:y,$=R&&!C;return h(`div`,{..._e,className:p(v,O?.root,l.dropdownLabel,l.dropdown,{[l.dropdownLabelColumn]:!ue}),style:{...oe,...k?.root},onMouseEnter:we,onMouseLeave:Te,children:[m(ae,{...C?{isOpen:!1}:{},onChange:e=>ke((e||{key:``}).key),itemToString:e=>e?String(e.key):``,selectedItem:A.find(e=>e.key===J)??null,onStateChange:e=>{typeof e.isOpen==`boolean`&&be(e.isOpen)},stateReducer:(e,t)=>F&&Object.prototype.hasOwnProperty.call(t,`isOpen`)?{...t,highlightedIndex:t.isOpen?A.indexOf(e.selectedItem):null}:t,children:({getItemProps:e,getMenuProps:t,getToggleButtonProps:i,closeMenu:a,isOpen:o,selectedItem:s,highlightedIndex:c,setHighlightedIndex:u})=>m(`div`,{children:h(`div`,{ref:H,onFocus:Ee,onBlur:De,className:p(l.dropdownInput,{[l.dropdownInputPlain]:P,[l.dropdownInputReadOnly]:C&&!S},O?.field),style:k?.field,children:[m(`button`,{tabIndex:b,type:`button`,disabled:S,"aria-readonly":C||void 0,className:p(l.dropdownInputButton,{[l.dropdownInputButtonDisabled]:S,[l.dropdownInputButtonReadOnly]:C&&!S},O?.control),style:{...E?{padding:`6px`,border:`none`}:{},...k?.control},...i(),onClick:e=>{i().onClick?.(e),w?.(e)},ref:L,children:Z?`\xA0`:X}),m(`button`,{type:`button`,tabIndex:-1,disabled:S,className:p(l.dropdownInputButtonIcon,O?.icon),style:k?.icon,...i(),onClick:e=>{i().onClick?.(e),w?.(e)},children:!S&&!C&&m(re,{icon:ie,className:p(l.dropdownInputButtonIconArrow,{[l.dropdownInputButtonIconArrowOpen]:o})})}),!S&&!C&&o?h(n,{children:[G&&m(ee,{onClose:a}),m(`div`,{...t({ref:e=>{U.current=e},"aria-label":y||N||void 0},{suppressRefError:!0}),style:G?Ce:void 0,className:p(l.dropdownInputListAnim,{[r.sheet]:G,[l.dropdownInputListAnimWider]:E&&!G}),children:m(te,{onScroll:de,className:p(l.dropdownInputList,G&&r.sheetScroll,O?.list),style:k?.list,setHighlightedIndex:u,children:A.map((t,n)=>m(`div`,{...e({index:n,item:t,disabled:!!t.disabled}),style:k?.option,className:p(l.dropdownInputListItem,O?.option,{[l.dropdownInputListItemActive]:c===n,[l.dropdownInputListItemSelected]:s===t,[l.dropdownInputListItemDisabled]:!!t.disabled}),children:t.label},t.key))})})]}):null,m(`fieldset`,{className:p(l.dropdownFieldset,{[l.dropdownBorderPlain]:P,[l.dropdownBorderFocused]:$,[l.dropdownBorderInvalid]:Y,[l.dropdownBorderError]:Y}),children:m(`legend`,{className:p(l.dropdownFieldsetLegend,{[l.dropdownFieldsetLegendActive]:j&&(M||$||!Z)}),children:m(`span`,{children:Ae})})}),j&&y&&h(`div`,{className:p(l.dropdownMatLabel,{[l.dropdownMatLabelFloating]:M||$||!Z},O?.label),style:k?.label,children:[y,Q]}),j&&N&&m(`div`,{className:p(l.dropdownPlaceholder,$&&!q&&l.dropdownPlaceholderShown),children:N})]})})}),y&&!j&&h(`div`,{className:p(l.dropdownLabelText,O?.label),style:k?.label,children:[y,Q]}),m(c,{variant:`error`,message:D?D.getCurrentErrorMessage():_||``,isVisible:Y&&(R||ve)})]})}export{g as default};
|
|
2
2
|
//# sourceMappingURL=dropdown.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown.mjs","names":[],"sources":["../../../../package/common/dropdown/dropdown.tsx"],"sourcesContent":["import React, { useState, useEffect, useLayoutEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport InfiniteBlock from 'components/common/infiniteBlock';\nimport BodyEnd from 'components/common/bodyEnd';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronDown as dropdownIcon } from '@fortawesome/free-solid-svg-icons';\nimport Downshift, { StateChangeOptions, DownshiftState } from 'downshift';\nimport Tooltip from 'components/common/tooltip';\n\nimport { useFloatingPosition } from '../floatingMenu/useFloatingPosition';\nimport { useComponentDefaults, usePresentationDefault } from '../configProvider';\nimport { useSheet } from '../hooks/useSheet';\nimport { useOverlay } from '../hooks/useOverlay';\nimport { Presentation } from '../floatingMenu/floatingMenu.types';\nimport styles from './dropdown.module.pcss';\nimport sheetStyles from '../styles/sheet.module.pcss';\nimport SheetBackdrop from '../sheetBackdrop';\nimport type { DropdownProps, DropdownItem } from './dropdown.types';\n\nfunction Dropdown(props: DropdownProps) {\n const {\n errorMessage = '',\n className = '',\n label = '',\n value = '',\n isValid = true,\n tabIndex = 0,\n isRequired = false,\n customProps = {},\n isRow = false,\n disabled = false,\n readOnly = false,\n onScroll = () => Promise.resolve(),\n onClick,\n onChange,\n onFocus: onFocusProp = null,\n onBlur: onBlurProp = null,\n onMouseEnter: onMouseEnterProp = null,\n onMouseLeave: onMouseLeaveProp = null,\n dropdownLabel: dropdownLabelProp,\n isDropdownListWider = false,\n inputClassName = '',\n dropDownIconClassName = '',\n dropDownClassName = '',\n formValidator = null,\n labelClassName = '',\n dropDownInputClassName = '',\n items = [],\n useMatLabelStyle = true,\n alwaysFloatLabel = false,\n placeholder = '',\n plainStyle = false,\n scrollToSelected = false,\n presentation: presentationProp,\n reactRef,\n ...rest\n } = useComponentDefaults('Dropdown', props);\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n const fvRef = useRef(formValidator);\n const triggerRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n const [menuIsOpen, setMenuIsOpen] = useState(false);\n\n // Explicit prop → this component's global default → the app-wide one → anchored.\n const appPresentation = usePresentationDefault();\n const presentation = presentationProp ?? appPresentation ?? Presentation.Default;\n const { isSheet, sheetStyle } = useSheet(presentation);\n\n useLayoutEffect(() => {\n const trigger = triggerRef.current;\n const menu = anchorRef.current;\n // A sheet spans the screen; only an anchored list matches the trigger's width.\n if (!menuIsOpen || isSheet || !trigger || !menu) return;\n const { width } = trigger.getBoundingClientRect();\n const { fontSize } = window.getComputedStyle(trigger);\n menu.style.width = `${width}px`;\n menu.style.fontSize = fontSize;\n }, [menuIsOpen, isSheet]);\n\n // A sheet isn't anchored to anything, so there's nothing to track, flip or clamp.\n useFloatingPosition({\n isOpen: menuIsOpen && !isSheet,\n triggerRef,\n anchorRef,\n panelRef: anchorRef,\n flipClassName: styles.dropdownInputListAnimFlip,\n });\n\n // Registered for as long as the list is open, not just as a sheet: it puts the list on the\n // overlay stack so an enclosing Modal doesn't also act on the Escape that closes it. No\n // `onEscape` of its own — Downshift already closes the list from the toggle button. Focus isn't\n // trapped: Downshift keeps focus on that button and drives the list from there.\n useOverlay({\n isActive: menuIsOpen,\n containerRef: anchorRef,\n trapFocus: false,\n lockScroll: isSheet,\n });\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!fvRef.current) return;\n fvRef.current.label = label ?? '';\n fvRef.current.validate();\n const listener = () => forceUpdate((n) => n + 1);\n fvRef.current.registerOnUpdateListener(listener);\n return () => fvRef.current?.removeOnUpdateListener(listener);\n }, [formValidator, label]);\n\n const onMouseEnterHandler = (event: React.MouseEvent) => {\n setIsHovered(true);\n onMouseEnterProp?.(event);\n };\n\n const onMouseLeaveHandler = (event: React.MouseEvent) => {\n setIsHovered(false);\n onMouseLeaveProp?.(event);\n };\n\n const onFocusHandler = (event: React.FocusEvent) => {\n setIsFocused(true);\n onFocusProp?.(event);\n };\n\n const onBlurHandler = (event: React.FocusEvent) => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n onBlurProp?.(event);\n };\n\n const hasError = (): boolean => {\n return formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n };\n\n const computedIsRequired = (): boolean => {\n return !!(\n isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required')\n );\n };\n\n const onChangeHandler = (val: string | number): void => {\n if (formValidator) {\n formValidator.set(val);\n onChange?.(formValidator.value, customProps);\n } else {\n onChange?.(val, customProps);\n }\n };\n\n let dropdownLabel = dropdownLabelProp;\n const currentValue = formValidator ? (formValidator.value as string | number) : value;\n const hasErr = hasError();\n\n items.forEach((item: DropdownItem) => {\n if (item.key === currentValue) {\n dropdownLabel = item.label as string;\n }\n });\n\n const displayValue = dropdownLabel || currentValue;\n const isDisplayBlank = displayValue == null || (typeof displayValue === 'string' && displayValue.trim() === '');\n\n const requiredMark = computedIsRequired() ? <span className={styles.requiredMark}>*</span> : null;\n const editedLabel = label && computedIsRequired() ? `${label} *` : label;\n\n const showFocus = isFocused && !readOnly;\n\n return (\n <div\n {...rest}\n className={cx(className, styles.dropdownLabel, styles.dropdown, {\n [styles.dropdownLabelColumn]: !isRow,\n })}\n onMouseEnter={onMouseEnterHandler}\n onMouseLeave={onMouseLeaveHandler}\n >\n <Downshift\n {...(readOnly ? { isOpen: false } : {})}\n onChange={(selection: DropdownItem | null) => onChangeHandler((selection || { key: '' }).key)}\n itemToString={(item: DropdownItem | null) => (item ? String(item.key) : '')}\n selectedItem={items.find((el) => el.key === currentValue) ?? null}\n onStateChange={(changes: StateChangeOptions<DropdownItem>) => {\n if (typeof changes.isOpen === 'boolean') setMenuIsOpen(changes.isOpen);\n }}\n stateReducer={(state: DownshiftState<DropdownItem>, changes: StateChangeOptions<DropdownItem>) => {\n if (scrollToSelected && Object.prototype.hasOwnProperty.call(changes, 'isOpen')) {\n return {\n ...changes,\n highlightedIndex: changes.isOpen ? items.indexOf(state.selectedItem as DropdownItem) : null,\n };\n }\n return changes;\n }}\n >\n {({\n getItemProps,\n getMenuProps,\n getToggleButtonProps,\n closeMenu,\n isOpen,\n selectedItem,\n highlightedIndex,\n setHighlightedIndex,\n }) => (\n <div>\n <div\n ref={triggerRef}\n onFocus={onFocusHandler}\n onBlur={onBlurHandler}\n className={cx(\n styles.dropdownInput,\n {\n [styles.dropdownInputPlain]: plainStyle,\n [styles.dropdownInputReadOnly]: readOnly && !disabled,\n },\n dropDownInputClassName,\n )}\n >\n <button\n tabIndex={tabIndex}\n type='button'\n disabled={disabled}\n aria-readonly={readOnly || undefined}\n style={isDropdownListWider ? { padding: '6px', border: 'none' } : {}}\n className={cx(\n styles.dropdownInputButton,\n {\n [styles.dropdownInputButtonDisabled]: disabled,\n [styles.dropdownInputButtonReadOnly]: readOnly && !disabled,\n },\n inputClassName,\n )}\n {...getToggleButtonProps()}\n onClick={(e: React.MouseEvent<HTMLButtonElement>) => {\n getToggleButtonProps().onClick?.(e);\n onClick?.(e);\n }}\n ref={reactRef}\n >\n {/* Non-breaking space when blank (same text-node layout as a\n real value) so the button keeps a full line of height. */}\n {isDisplayBlank ? '\\u00A0' : displayValue}\n </button>\n <button\n type='button'\n tabIndex={-1}\n disabled={disabled}\n className={cx(styles.dropdownInputButtonIcon, dropDownIconClassName)}\n {...getToggleButtonProps()}\n onClick={(e: React.MouseEvent<HTMLButtonElement>) => {\n getToggleButtonProps().onClick?.(e);\n onClick?.(e);\n }}\n >\n {!disabled && !readOnly && (\n <FontAwesomeIcon\n icon={dropdownIcon}\n className={cx(styles.dropdownInputButtonIconArrow, {\n [styles.dropdownInputButtonIconArrowOpen]: isOpen,\n })}\n />\n )}\n </button>\n {!disabled && !readOnly && isOpen ? (\n <BodyEnd>\n {isSheet && <SheetBackdrop onClose={closeMenu} />}\n <div\n {...getMenuProps(\n {\n ref: (node: HTMLDivElement | null) => {\n anchorRef.current = node;\n },\n 'aria-label': label || placeholder || undefined,\n },\n { suppressRefError: true },\n )}\n style={isSheet ? sheetStyle : undefined}\n className={cx(styles.dropdownInputListAnim, {\n [sheetStyles.sheet]: isSheet,\n [styles.dropdownInputListAnimWider]: isDropdownListWider && !isSheet,\n })}\n >\n <InfiniteBlock\n onScroll={onScroll}\n className={cx(styles.dropdownInputList, isSheet && sheetStyles.sheetScroll)}\n setHighlightedIndex={setHighlightedIndex}\n >\n {items.map((item: DropdownItem, index: number) => (\n <div\n key={item.key}\n {...getItemProps({ index, item, disabled: !!item.disabled })}\n className={cx(styles.dropdownInputListItem, dropDownClassName, {\n [styles.dropdownInputListItemActive]: highlightedIndex === index,\n [styles.dropdownInputListItemSelected]: selectedItem === item,\n [styles.dropdownInputListItemDisabled]: !!item.disabled,\n })}\n >\n {item.label}\n </div>\n ))}\n </InfiniteBlock>\n </div>\n </BodyEnd>\n ) : null}\n <fieldset\n className={cx(styles.dropdownFieldset, {\n [styles.dropdownBorderPlain]: plainStyle,\n [styles.dropdownBorderFocused]: showFocus,\n [styles.dropdownBorderInvalid]: hasErr,\n [styles.dropdownBorderError]: hasErr,\n })}\n >\n <legend\n className={cx(styles.dropdownFieldsetLegend, {\n [styles.dropdownFieldsetLegendActive]:\n useMatLabelStyle && (alwaysFloatLabel || showFocus || !isDisplayBlank),\n })}\n >\n <span>{editedLabel}</span>\n </legend>\n </fieldset>\n {useMatLabelStyle && label && (\n <div\n className={cx(styles.dropdownMatLabel, {\n [styles.dropdownMatLabelFloating]: alwaysFloatLabel || showFocus || !isDisplayBlank,\n })}\n >\n {label}\n {requiredMark}\n </div>\n )}\n {useMatLabelStyle && placeholder && (\n <div\n className={cx(\n styles.dropdownPlaceholder,\n showFocus && !dropdownLabel && styles.dropdownPlaceholderShown,\n )}\n >\n {placeholder}\n </div>\n )}\n </div>\n </div>\n )}\n </Downshift>\n {label && !useMatLabelStyle && (\n <div className={cx(styles.dropdownLabelText, labelClassName)}>\n {label}\n {requiredMark}\n </div>\n )}\n <Tooltip\n variant='error'\n message={formValidator ? formValidator.getCurrentErrorMessage() : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n\nexport default Dropdown;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dropdown.mjs","names":[],"sources":["../../../../package/common/dropdown/dropdown.tsx"],"sourcesContent":["import React, { useState, useEffect, useLayoutEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport InfiniteBlock from 'components/common/infiniteBlock';\nimport BodyEnd from 'components/common/bodyEnd';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faChevronDown as dropdownIcon } from '@fortawesome/free-solid-svg-icons';\nimport Downshift, { StateChangeOptions, DownshiftState } from 'downshift';\nimport Tooltip from 'components/common/tooltip';\n\nimport { useFloatingPosition } from '../floatingMenu/useFloatingPosition';\nimport { useComponentDefaults, usePresentationDefault } from '../configProvider';\nimport { useSheet } from '../hooks/useSheet';\nimport { useOverlay } from '../hooks/useOverlay';\nimport { Presentation } from '../floatingMenu/floatingMenu.types';\nimport styles from './dropdown.module.pcss';\nimport sheetStyles from '../styles/sheet.module.pcss';\nimport SheetBackdrop from '../sheetBackdrop';\nimport type { DropdownProps, DropdownItem } from './dropdown.types';\n\nfunction Dropdown(props: DropdownProps) {\n const {\n errorMessage = '',\n className = '',\n style,\n label = '',\n value = '',\n isValid = true,\n tabIndex = 0,\n isRequired = false,\n customProps = {},\n isRow = false,\n disabled = false,\n readOnly = false,\n onScroll = () => Promise.resolve(),\n onClick,\n onChange,\n onFocus: onFocusProp = null,\n onBlur: onBlurProp = null,\n onMouseEnter: onMouseEnterProp = null,\n onMouseLeave: onMouseLeaveProp = null,\n dropdownLabel: dropdownLabelProp,\n isDropdownListWider = false,\n formValidator = null,\n classNames,\n styles: slotStyles,\n items = [],\n useMatLabelStyle = true,\n alwaysFloatLabel = false,\n placeholder = '',\n plainStyle = false,\n scrollToSelected = false,\n presentation: presentationProp,\n reactRef,\n ...rest\n } = useComponentDefaults('Dropdown', props);\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n const fvRef = useRef(formValidator);\n const triggerRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLDivElement>(null);\n const [menuIsOpen, setMenuIsOpen] = useState(false);\n\n // Explicit prop → this component's global default → the app-wide one → anchored.\n const appPresentation = usePresentationDefault();\n const presentation = presentationProp ?? appPresentation ?? Presentation.Default;\n const { isSheet, sheetStyle } = useSheet(presentation);\n\n useLayoutEffect(() => {\n const trigger = triggerRef.current;\n const menu = anchorRef.current;\n // A sheet spans the screen; only an anchored list matches the trigger's width.\n if (!menuIsOpen || isSheet || !trigger || !menu) return;\n const { width } = trigger.getBoundingClientRect();\n const { fontSize } = window.getComputedStyle(trigger);\n menu.style.width = `${width}px`;\n menu.style.fontSize = fontSize;\n }, [menuIsOpen, isSheet]);\n\n // A sheet isn't anchored to anything, so there's nothing to track, flip or clamp.\n useFloatingPosition({\n isOpen: menuIsOpen && !isSheet,\n triggerRef,\n anchorRef,\n panelRef: anchorRef,\n flipClassName: styles.dropdownInputListAnimFlip,\n });\n\n // Registered for as long as the list is open, not just as a sheet: it puts the list on the\n // overlay stack so an enclosing Modal doesn't also act on the Escape that closes it. No\n // `onEscape` of its own — Downshift already closes the list from the toggle button. Focus isn't\n // trapped: Downshift keeps focus on that button and drives the list from there.\n useOverlay({\n isActive: menuIsOpen,\n containerRef: anchorRef,\n trapFocus: false,\n lockScroll: isSheet,\n });\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!fvRef.current) return;\n fvRef.current.label = label ?? '';\n fvRef.current.validate();\n const listener = () => forceUpdate((n) => n + 1);\n fvRef.current.registerOnUpdateListener(listener);\n return () => fvRef.current?.removeOnUpdateListener(listener);\n }, [formValidator, label]);\n\n const onMouseEnterHandler = (event: React.MouseEvent) => {\n setIsHovered(true);\n onMouseEnterProp?.(event);\n };\n\n const onMouseLeaveHandler = (event: React.MouseEvent) => {\n setIsHovered(false);\n onMouseLeaveProp?.(event);\n };\n\n const onFocusHandler = (event: React.FocusEvent) => {\n setIsFocused(true);\n onFocusProp?.(event);\n };\n\n const onBlurHandler = (event: React.FocusEvent) => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n onBlurProp?.(event);\n };\n\n const hasError = (): boolean => {\n return formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n };\n\n const computedIsRequired = (): boolean => {\n return !!(\n isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required')\n );\n };\n\n const onChangeHandler = (val: string | number): void => {\n if (formValidator) {\n formValidator.set(val);\n onChange?.(formValidator.value, customProps);\n } else {\n onChange?.(val, customProps);\n }\n };\n\n let dropdownLabel = dropdownLabelProp;\n const currentValue = formValidator ? (formValidator.value as string | number) : value;\n const hasErr = hasError();\n\n items.forEach((item: DropdownItem) => {\n if (item.key === currentValue) {\n dropdownLabel = item.label as string;\n }\n });\n\n const displayValue = dropdownLabel || currentValue;\n const isDisplayBlank = displayValue == null || (typeof displayValue === 'string' && displayValue.trim() === '');\n\n const requiredMark = computedIsRequired() ? <span className={styles.requiredMark}>*</span> : null;\n const editedLabel = label && computedIsRequired() ? `${label} *` : label;\n\n const showFocus = isFocused && !readOnly;\n\n return (\n <div\n {...rest}\n className={cx(className, classNames?.root, styles.dropdownLabel, styles.dropdown, {\n [styles.dropdownLabelColumn]: !isRow,\n })}\n style={{ ...style, ...slotStyles?.root }}\n onMouseEnter={onMouseEnterHandler}\n onMouseLeave={onMouseLeaveHandler}\n >\n <Downshift\n {...(readOnly ? { isOpen: false } : {})}\n onChange={(selection: DropdownItem | null) => onChangeHandler((selection || { key: '' }).key)}\n itemToString={(item: DropdownItem | null) => (item ? String(item.key) : '')}\n selectedItem={items.find((el) => el.key === currentValue) ?? null}\n onStateChange={(changes: StateChangeOptions<DropdownItem>) => {\n if (typeof changes.isOpen === 'boolean') setMenuIsOpen(changes.isOpen);\n }}\n stateReducer={(state: DownshiftState<DropdownItem>, changes: StateChangeOptions<DropdownItem>) => {\n if (scrollToSelected && Object.prototype.hasOwnProperty.call(changes, 'isOpen')) {\n return {\n ...changes,\n highlightedIndex: changes.isOpen ? items.indexOf(state.selectedItem as DropdownItem) : null,\n };\n }\n return changes;\n }}\n >\n {({\n getItemProps,\n getMenuProps,\n getToggleButtonProps,\n closeMenu,\n isOpen,\n selectedItem,\n highlightedIndex,\n setHighlightedIndex,\n }) => (\n <div>\n <div\n ref={triggerRef}\n onFocus={onFocusHandler}\n onBlur={onBlurHandler}\n className={cx(\n styles.dropdownInput,\n {\n [styles.dropdownInputPlain]: plainStyle,\n [styles.dropdownInputReadOnly]: readOnly && !disabled,\n },\n classNames?.field,\n )}\n style={slotStyles?.field}\n >\n <button\n tabIndex={tabIndex}\n type='button'\n disabled={disabled}\n aria-readonly={readOnly || undefined}\n className={cx(\n styles.dropdownInputButton,\n {\n [styles.dropdownInputButtonDisabled]: disabled,\n [styles.dropdownInputButtonReadOnly]: readOnly && !disabled,\n },\n classNames?.control,\n )}\n style={{ ...(isDropdownListWider ? { padding: '6px', border: 'none' } : {}), ...slotStyles?.control }}\n {...getToggleButtonProps()}\n onClick={(e: React.MouseEvent<HTMLButtonElement>) => {\n getToggleButtonProps().onClick?.(e);\n onClick?.(e);\n }}\n ref={reactRef}\n >\n {/* Non-breaking space when blank (same text-node layout as a\n real value) so the button keeps a full line of height. */}\n {isDisplayBlank ? '\\u00A0' : displayValue}\n </button>\n <button\n type='button'\n tabIndex={-1}\n disabled={disabled}\n className={cx(styles.dropdownInputButtonIcon, classNames?.icon)}\n style={slotStyles?.icon}\n {...getToggleButtonProps()}\n onClick={(e: React.MouseEvent<HTMLButtonElement>) => {\n getToggleButtonProps().onClick?.(e);\n onClick?.(e);\n }}\n >\n {!disabled && !readOnly && (\n <FontAwesomeIcon\n icon={dropdownIcon}\n className={cx(styles.dropdownInputButtonIconArrow, {\n [styles.dropdownInputButtonIconArrowOpen]: isOpen,\n })}\n />\n )}\n </button>\n {!disabled && !readOnly && isOpen ? (\n <BodyEnd>\n {isSheet && <SheetBackdrop onClose={closeMenu} />}\n <div\n {...getMenuProps(\n {\n ref: (node: HTMLDivElement | null) => {\n anchorRef.current = node;\n },\n 'aria-label': label || placeholder || undefined,\n },\n { suppressRefError: true },\n )}\n style={isSheet ? sheetStyle : undefined}\n className={cx(styles.dropdownInputListAnim, {\n [sheetStyles.sheet]: isSheet,\n [styles.dropdownInputListAnimWider]: isDropdownListWider && !isSheet,\n })}\n >\n <InfiniteBlock\n onScroll={onScroll}\n className={cx(styles.dropdownInputList, isSheet && sheetStyles.sheetScroll, classNames?.list)}\n style={slotStyles?.list}\n setHighlightedIndex={setHighlightedIndex}\n >\n {items.map((item: DropdownItem, index: number) => (\n <div\n key={item.key}\n {...getItemProps({ index, item, disabled: !!item.disabled })}\n style={slotStyles?.option}\n className={cx(styles.dropdownInputListItem, classNames?.option, {\n [styles.dropdownInputListItemActive]: highlightedIndex === index,\n [styles.dropdownInputListItemSelected]: selectedItem === item,\n [styles.dropdownInputListItemDisabled]: !!item.disabled,\n })}\n >\n {item.label}\n </div>\n ))}\n </InfiniteBlock>\n </div>\n </BodyEnd>\n ) : null}\n <fieldset\n className={cx(styles.dropdownFieldset, {\n [styles.dropdownBorderPlain]: plainStyle,\n [styles.dropdownBorderFocused]: showFocus,\n [styles.dropdownBorderInvalid]: hasErr,\n [styles.dropdownBorderError]: hasErr,\n })}\n >\n <legend\n className={cx(styles.dropdownFieldsetLegend, {\n [styles.dropdownFieldsetLegendActive]:\n useMatLabelStyle && (alwaysFloatLabel || showFocus || !isDisplayBlank),\n })}\n >\n <span>{editedLabel}</span>\n </legend>\n </fieldset>\n {useMatLabelStyle && label && (\n <div\n className={cx(\n styles.dropdownMatLabel,\n {\n [styles.dropdownMatLabelFloating]: alwaysFloatLabel || showFocus || !isDisplayBlank,\n },\n // The floating and the stacked label are two renderings of\n // the same thing, so one slot reaches whichever is in use.\n classNames?.label,\n )}\n style={slotStyles?.label}\n >\n {label}\n {requiredMark}\n </div>\n )}\n {useMatLabelStyle && placeholder && (\n <div\n className={cx(\n styles.dropdownPlaceholder,\n showFocus && !dropdownLabel && styles.dropdownPlaceholderShown,\n )}\n >\n {placeholder}\n </div>\n )}\n </div>\n </div>\n )}\n </Downshift>\n {label && !useMatLabelStyle && (\n <div className={cx(styles.dropdownLabelText, classNames?.label)} style={slotStyles?.label}>\n {label}\n {requiredMark}\n </div>\n )}\n <Tooltip\n variant='error'\n message={formValidator ? formValidator.getCurrentErrorMessage() : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n\nexport default Dropdown;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{useLabels as e}from"../configProvider/useLabels.mjs";import{renderIcon as t}from"../utils/renderIcon.mjs";import n from"./emptyState.module.mjs";import r from"classnames";import{jsx as i,jsxs as a}from"react/jsx-runtime";var o={empty:`No entries available`};function s({className:s,icon:c,children:l,labels:u,style:d,classNames:f,styles:p,...m}){let h=e(`EmptyState`,u,o);return a(`div`,{...m,className:r(n.emptyState,s,f?.root),style:{...d,...p?.root},children:[c?t(c,{className:f?.icon,style:p?.icon}):null,i(`div`,{className:f?.text,style:p?.text,children:l??h.empty})]})}export{s as default};
|
|
2
2
|
//# sourceMappingURL=emptyState.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emptyState.mjs","names":[],"sources":["../../../../package/common/emptyState/emptyState.tsx"],"sourcesContent":["import cx from 'classnames';\nimport type { ReactElement } from 'react';\nimport
|
|
1
|
+
{"version":3,"file":"emptyState.mjs","names":[],"sources":["../../../../package/common/emptyState/emptyState.tsx"],"sourcesContent":["import cx from 'classnames';\nimport type { ReactElement } from 'react';\n\nimport styles from './emptyState.module.pcss';\nimport { useLabels } from '../configProvider';\nimport { renderIcon } from '../utils/renderIcon';\nimport type { EmptyStateLabels, EmptyStateProps } from './emptyState.types';\n\nconst DEFAULT_LABELS: Required<EmptyStateLabels> = {\n empty: 'No entries available',\n};\n\nexport default function EmptyState({\n className,\n icon,\n children,\n labels,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: EmptyStateProps): ReactElement {\n const text = useLabels('EmptyState', labels, DEFAULT_LABELS);\n return (\n <div\n {...rest}\n className={cx(styles.emptyState, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n {icon ? renderIcon(icon, { className: classNames?.icon, style: slotStyles?.icon }) : null}\n <div className={classNames?.text} style={slotStyles?.text}>\n {children ?? text.empty}\n </div>\n </div>\n );\n}\n"],"mappings":"oOAQA,IAAM,EAA6C,CACjD,MAAO,sBACT,EAEA,SAAwB,EAAW,CACjC,YACA,OACA,WACA,SACA,QACA,aACA,OAAQ,EACR,GAAG,GAC6B,CAChC,IAAM,EAAO,EAAU,aAAc,EAAQ,CAAc,EAC3D,OACE,EAAC,MAAD,CACE,GAAI,EACJ,UAAW,EAAG,EAAO,WAAY,EAAW,GAAY,IAAI,EAC5D,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,EAHzC,SAAA,CAKG,EAAO,EAAW,EAAM,CAAE,UAAW,GAAY,KAAM,MAAO,GAAY,IAAK,CAAC,EAAI,KACrF,EAAC,MAAD,CAAK,UAAW,GAAY,KAAM,MAAO,GAAY,KAClD,SAAA,GAAY,EAAK,KACf,CAAA,CACF,GAET"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ButtonSize as e,ButtonStyleType as t}from"../../../button/button.types.mjs";import n from"../../../button/button.mjs";import r from"./fabBase.module.mjs";import i from"classnames";import{jsx as a}from"react/jsx-runtime";var o={default:null,mini:r.fabSizeMini};function s({children:
|
|
1
|
+
import{ButtonSize as e,ButtonStyleType as t}from"../../../button/button.types.mjs";import n from"../../../button/button.mjs";import r from"./fabBase.module.mjs";import i from"classnames";import{jsx as a}from"react/jsx-runtime";var o={default:null,mini:r.fabSizeMini};function s({style:s,children:c=null,size:l=`default`,className:u=``,styleType:d=t.Primary,onClick:f=()=>{}}){return a(n,{styleType:d,size:e.Icon,className:i(r.fab,o[l],u),style:s,onClick:f,children:a(`div`,{className:r.fabContentContainer,children:a(`div`,{className:r.fabContent,children:c})})})}export{s as default};
|
|
2
2
|
//# sourceMappingURL=fabBase.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fabBase.mjs","names":[],"sources":["../../../../../../package/common/fab/components/fabBase/fabBase.tsx"],"sourcesContent":["import cx from 'classnames';\n\nimport Button from 'components/common/button';\nimport { ButtonSize, ButtonStyleType } from 'components/common/button/button.types';\nimport type { FabBaseProps, FabBaseSize } from './fabBase.types';\n\nimport styles from './fabBase.module.pcss';\n\nconst sizeClass: Record<FabBaseSize, string | null> = {\n default: null,\n mini: styles.fabSizeMini,\n};\n\nfunction FabBase({\n children = null,\n size = 'default',\n className = '',\n styleType = ButtonStyleType.Primary,\n onClick = () => {},\n}: FabBaseProps) {\n return (\n /* Icon is the only size that adds no padding. Any other one pushes past the width set\n below through Button's `min-width: min-content`, and the circle becomes an ellipse. */\n <Button\n styleType={styleType}\n size={ButtonSize.Icon}\n className={cx(styles.fab, sizeClass[size], className)}\n onClick={onClick}\n >\n <div className={styles.fabContentContainer}>\n <div className={styles.fabContent}>{children}</div>\n </div>\n </Button>\n );\n}\n\nexport default FabBase;\n"],"mappings":"mOAQA,IAAM,EAAgD,CACpD,QAAS,KACT,KAAM,EAAO,WACf,EAEA,SAAS,EAAQ,CACf,WAAW,KACX,OAAO,UACP,YAAY,GACZ,YAAY,EAAgB,QAC5B,cAAgB,CAAC,GACF,CACf,OAGE,EAAC,EAAD,CACa,YACX,KAAM,EAAW,KACjB,UAAW,EAAG,EAAO,IAAK,EAAU,GAAO,CAAS,
|
|
1
|
+
{"version":3,"file":"fabBase.mjs","names":[],"sources":["../../../../../../package/common/fab/components/fabBase/fabBase.tsx"],"sourcesContent":["import cx from 'classnames';\n\nimport Button from 'components/common/button';\nimport { ButtonSize, ButtonStyleType } from 'components/common/button/button.types';\nimport type { FabBaseProps, FabBaseSize } from './fabBase.types';\n\nimport styles from './fabBase.module.pcss';\n\nconst sizeClass: Record<FabBaseSize, string | null> = {\n default: null,\n mini: styles.fabSizeMini,\n};\n\nfunction FabBase({\n style,\n children = null,\n size = 'default',\n className = '',\n styleType = ButtonStyleType.Primary,\n onClick = () => {},\n}: FabBaseProps) {\n return (\n /* Icon is the only size that adds no padding. Any other one pushes past the width set\n below through Button's `min-width: min-content`, and the circle becomes an ellipse. */\n <Button\n styleType={styleType}\n size={ButtonSize.Icon}\n className={cx(styles.fab, sizeClass[size], className)}\n style={style}\n onClick={onClick}\n >\n <div className={styles.fabContentContainer}>\n <div className={styles.fabContent}>{children}</div>\n </div>\n </Button>\n );\n}\n\nexport default FabBase;\n"],"mappings":"mOAQA,IAAM,EAAgD,CACpD,QAAS,KACT,KAAM,EAAO,WACf,EAEA,SAAS,EAAQ,CACf,QACA,WAAW,KACX,OAAO,UACP,YAAY,GACZ,YAAY,EAAgB,QAC5B,cAAgB,CAAC,GACF,CACf,OAGE,EAAC,EAAD,CACa,YACX,KAAM,EAAW,KACjB,UAAW,EAAG,EAAO,IAAK,EAAU,GAAO,CAAS,EAC7C,QACE,UAET,SAAA,EAAC,MAAD,CAAK,UAAW,EAAO,oBACrB,SAAA,EAAC,MAAD,CAAK,UAAW,EAAO,WAAa,UAAc,CAAA,CAC/C,CAAA,CACC,CAAA,CAEZ"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ButtonStyleType as e}from"../button/button.types.mjs";import{renderIcon as t}from"../utils/renderIcon.mjs";import n from"./components/fabBase/fabBase.mjs";import r from"./fab.module.mjs";import{useState as i}from"react";import a from"classnames";import{FontAwesomeIcon as o}from"@fortawesome/react-fontawesome";import{faPlus as s}from"@fortawesome/free-solid-svg-icons";import{jsx as c,jsxs as l}from"react/jsx-runtime";function u({children:u=null,size:d=`default`,menuEntries:f=[],onMenuEntryClicked:p=()=>{},onClick:m=()=>{},closeMenuOnEntryClicked:h=!0,...
|
|
1
|
+
import{ButtonStyleType as e}from"../button/button.types.mjs";import{renderIcon as t}from"../utils/renderIcon.mjs";import n from"./components/fabBase/fabBase.mjs";import r from"./fab.module.mjs";import{useState as i}from"react";import a from"classnames";import{FontAwesomeIcon as o}from"@fortawesome/react-fontawesome";import{faPlus as s}from"@fortawesome/free-solid-svg-icons";import{jsx as c,jsxs as l}from"react/jsx-runtime";function u({children:u=null,size:d=`default`,menuEntries:f=[],onMenuEntryClicked:p=()=>{},onClick:m=()=>{},closeMenuOnEntryClicked:h=!0,className:g,style:_,classNames:v,styles:y,...b}){let[x,S]=i(!1);function C(){f.length>0&&S(e=>!e),m()}function w(e,t){e.stopPropagation(),h&&S(!1),p(t)}return l(`div`,{...b,className:a(r.fabContainer,g,v?.root),style:{..._,...y?.root},children:[c(`div`,{className:a(r.fabMenuBackdrop,x&&r.fabMenuBackdropOpen,v?.backdrop),style:y?.backdrop,onClick:e=>{e.stopPropagation(),S(!1)}}),c(`div`,{onClick:e=>e.stopPropagation(),children:c(n,{className:a(r.fab,v?.button),style:y?.button,size:d,onClick:C,children:l(`div`,{className:a(r.fabIcon,x&&r.fabIconMenuOpen,v?.icon),style:y?.icon,children:[c(`div`,{className:a(r.fabIconContent,!x&&r.fabIconContentShown),children:u}),c(`div`,{className:a(r.fabIconContent,x&&r.fabIconContentShown),children:c(o,{icon:s})})]})})}),c(`div`,{className:a(r.fabMenu,v?.menu),style:y?.menu,children:f.map(({id:i,label:o,icon:s})=>l(`div`,{className:a(r.fabMenuEntry,x&&r.fabMenuEntryShown,v?.menuEntry),style:y?.menuEntry,onClick:e=>w(e,i),children:[o&&c(`div`,{className:r.fabMenuEntryLabelContainer,children:c(`div`,{className:a(r.fabMenuEntryLabel,v?.menuEntryLabel),style:y?.menuEntryLabel,children:o})}),c(n,{size:`mini`,styleType:e.Default,children:t(s)})]},i))})]})}export{u as default};
|
|
2
2
|
//# sourceMappingURL=fab.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fab.mjs","names":[],"sources":["../../../../package/common/fab/fab.tsx"],"sourcesContent":["import { useState } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faPlus as addIcon } from '@fortawesome/free-solid-svg-icons';\nimport { ButtonStyleType } from '../button/button.types';\n\nimport FabBase from './components/fabBase';\nimport type { FabProps } from './fab.types';\n\nimport styles from './fab.module.pcss';\nimport { renderIcon } from '../utils/renderIcon';\n\nfunction Fab({\n children = null,\n size = 'default',\n menuEntries = [],\n onMenuEntryClicked = () => {},\n onClick = () => {},\n closeMenuOnEntryClicked = true,\n ...rest\n}: FabProps) {\n const [menuOpen, setMenuOpen] = useState(false);\n\n function handleFabClick() {\n if (menuEntries.length > 0) setMenuOpen((prev) => !prev);\n onClick();\n }\n\n function handleEntryClick(e: React.MouseEvent, id: string) {\n e.stopPropagation();\n if (closeMenuOnEntryClicked) setMenuOpen(false);\n onMenuEntryClicked(id);\n }\n\n return (\n <div
|
|
1
|
+
{"version":3,"file":"fab.mjs","names":[],"sources":["../../../../package/common/fab/fab.tsx"],"sourcesContent":["import { useState } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faPlus as addIcon } from '@fortawesome/free-solid-svg-icons';\nimport { ButtonStyleType } from '../button/button.types';\n\nimport FabBase from './components/fabBase';\nimport type { FabProps } from './fab.types';\n\nimport styles from './fab.module.pcss';\nimport { renderIcon } from '../utils/renderIcon';\n\nfunction Fab({\n children = null,\n size = 'default',\n menuEntries = [],\n onMenuEntryClicked = () => {},\n onClick = () => {},\n closeMenuOnEntryClicked = true,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: FabProps) {\n const [menuOpen, setMenuOpen] = useState(false);\n\n function handleFabClick() {\n if (menuEntries.length > 0) setMenuOpen((prev) => !prev);\n onClick();\n }\n\n function handleEntryClick(e: React.MouseEvent, id: string) {\n e.stopPropagation();\n if (closeMenuOnEntryClicked) setMenuOpen(false);\n onMenuEntryClicked(id);\n }\n\n return (\n <div\n {...rest}\n className={cx(styles.fabContainer, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <div\n className={cx(styles.fabMenuBackdrop, menuOpen && styles.fabMenuBackdropOpen, classNames?.backdrop)}\n style={slotStyles?.backdrop}\n onClick={(e) => {\n e.stopPropagation();\n setMenuOpen(false);\n }}\n />\n <div onClick={(e) => e.stopPropagation()}>\n <FabBase\n className={cx(styles.fab, classNames?.button)}\n style={slotStyles?.button}\n size={size}\n onClick={handleFabClick}\n >\n <div\n className={cx(styles.fabIcon, menuOpen && styles.fabIconMenuOpen, classNames?.icon)}\n style={slotStyles?.icon}\n >\n <div className={cx(styles.fabIconContent, !menuOpen && styles.fabIconContentShown)}>{children}</div>\n <div className={cx(styles.fabIconContent, menuOpen && styles.fabIconContentShown)}>\n <FontAwesomeIcon icon={addIcon} />\n </div>\n </div>\n </FabBase>\n </div>\n <div className={cx(styles.fabMenu, classNames?.menu)} style={slotStyles?.menu}>\n {menuEntries.map(({ id, label, icon }) => (\n <div\n key={id}\n className={cx(styles.fabMenuEntry, menuOpen && styles.fabMenuEntryShown, classNames?.menuEntry)}\n style={slotStyles?.menuEntry}\n onClick={(e) => handleEntryClick(e, id)}\n >\n {label && (\n <div className={styles.fabMenuEntryLabelContainer}>\n <div\n className={cx(styles.fabMenuEntryLabel, classNames?.menuEntryLabel)}\n style={slotStyles?.menuEntryLabel}\n >\n {label}\n </div>\n </div>\n )}\n <FabBase size='mini' styleType={ButtonStyleType.Default}>\n {renderIcon(icon)}\n </FabBase>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nexport default Fab;\n"],"mappings":"2aAYA,SAAS,EAAI,CACX,WAAW,KACX,OAAO,UACP,cAAc,CAAC,EACf,yBAA2B,CAAC,EAC5B,cAAgB,CAAC,EACjB,0BAA0B,GAC1B,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACQ,CACX,GAAM,CAAC,EAAU,GAAe,EAAS,EAAK,EAE9C,SAAS,GAAiB,CACpB,EAAY,OAAS,GAAG,EAAa,GAAS,CAAC,CAAI,EACvD,EAAQ,CACV,CAEA,SAAS,EAAiB,EAAqB,EAAY,CACzD,EAAE,gBAAgB,EACd,GAAyB,EAAY,EAAK,EAC9C,EAAmB,CAAE,CACvB,CAEA,OACE,EAAC,MAAD,CACE,GAAI,EACJ,UAAW,EAAG,EAAO,aAAc,EAAW,GAAY,IAAI,EAC9D,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,EAHzC,SAAA,CAKE,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,gBAAiB,GAAY,EAAO,oBAAqB,GAAY,QAAQ,EAClG,MAAO,GAAY,SACnB,QAAU,GAAM,CACd,EAAE,gBAAgB,EAClB,EAAY,EAAK,CACnB,CACD,CAAA,EACD,EAAC,MAAD,CAAK,QAAU,GAAM,EAAE,gBAAgB,EACrC,SAAA,EAAC,EAAD,CACE,UAAW,EAAG,EAAO,IAAK,GAAY,MAAM,EAC5C,MAAO,GAAY,OACb,OACN,QAAS,EAET,SAAA,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,QAAS,GAAY,EAAO,gBAAiB,GAAY,IAAI,EAClF,MAAO,GAAY,KAFrB,SAAA,CAIE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,eAAgB,CAAC,GAAY,EAAO,mBAAmB,EAAI,UAAc,CAAA,EACnG,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,eAAgB,GAAY,EAAO,mBAAmB,EAC9E,SAAA,EAAC,EAAD,CAAiB,KAAM,CAAU,CAAA,CAC9B,CAAA,CACF,GACE,CAAA,CACN,CAAA,EACL,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,QAAS,GAAY,IAAI,EAAG,MAAO,GAAY,KACtE,SAAA,EAAY,KAAK,CAAE,KAAI,QAAO,UAC7B,EAAC,MAAD,CAEE,UAAW,EAAG,EAAO,aAAc,GAAY,EAAO,kBAAmB,GAAY,SAAS,EAC9F,MAAO,GAAY,UACnB,QAAU,GAAM,EAAiB,EAAG,CAAE,EAJxC,SAAA,CAMG,GACC,EAAC,MAAD,CAAK,UAAW,EAAO,2BACrB,SAAA,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,kBAAmB,GAAY,cAAc,EAClE,MAAO,GAAY,eAElB,SAAA,CACE,CAAA,CACF,CAAA,EAEP,EAAC,EAAD,CAAS,KAAK,OAAO,UAAW,EAAgB,QAC7C,SAAA,EAAW,CAAI,CACT,CAAA,CACN,CAlBE,EAAA,CAkBF,CACN,CACE,CAAA,CACF,GAET"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"../loading/spinnerLoading/index.mjs";import t from"./infiniteBlock.module.mjs";import n,{useCallback as r,useEffect as i,useRef as a,useState as o}from"react";import s from"classnames";import{Fragment as c,jsx as l,jsxs as u}from"react/jsx-runtime";function d(e){return e==null||typeof e==`boolean`?``:typeof e==`string`||typeof e==`number`?String(e):Array.isArray(e)?e.map(d).join(``):n.isValidElement(e)?d(e.props.children):``}function f(e,t,n){return e===-1?t>0?0:n-1:(e+t+n)%n}function p(e,t,n){let[r,s]=o(!1),c=a(!1),l=a(null),u=a(t);return i(()=>{u.current=t}),i(()=>{let t=e.current,r=l.current;if(n||!t||!r)return;let i=!1,a=()=>{c.current||(c.current=!0,s(!0),u.current().catch(()=>null).finally(()=>{i||(c.current=!1,s(!1),o.unobserve(r),o.observe(r))}))},o=new IntersectionObserver(([e])=>{e.isIntersecting&&a()},{root:t});return o.observe(r),()=>{i=!0,o.disconnect()}},[e,n]),{isLoading:r,sentinelRef:l}}function m(e,t){let i=a(null),o=a(-1),s=a(null);return{containerRef:i,onKeyDown:r(r=>{let a=i.current;if(!a)return;let c=n.Children.toArray(e);if(c.length===0)return;let l=o.current;if(r.key===`ArrowDown`)r.preventDefault(),l=f(l,1,c.length);else if(r.key===`ArrowUp`)r.preventDefault(),l=f(l,-1,c.length);else if(r.key.length===1){let e=r.key.toLowerCase(),t=s.current===r.key?l+1:0,n=t=>d(t).toLowerCase().startsWith(e),i=c.slice(t).findIndex(n),a=i===-1?c.slice(0,t).findIndex(n):t+i;if(s.current=r.key,a===-1)return;l=a}else return;s.current=r.key,o.current=l;let u=a.children[l];if(u){let e=u.offsetTop,t=e+u.offsetHeight;e<a.scrollTop?a.scrollTop=e:t>a.scrollTop+a.clientHeight&&(a.scrollTop=t-a.clientHeight)}t(l)},[e,t])}}function h({children:n,onScroll:r,className:i=``,isDataLoading:
|
|
1
|
+
import e from"../loading/spinnerLoading/index.mjs";import t from"./infiniteBlock.module.mjs";import n,{useCallback as r,useEffect as i,useRef as a,useState as o}from"react";import s from"classnames";import{Fragment as c,jsx as l,jsxs as u}from"react/jsx-runtime";function d(e){return e==null||typeof e==`boolean`?``:typeof e==`string`||typeof e==`number`?String(e):Array.isArray(e)?e.map(d).join(``):n.isValidElement(e)?d(e.props.children):``}function f(e,t,n){return e===-1?t>0?0:n-1:(e+t+n)%n}function p(e,t,n){let[r,s]=o(!1),c=a(!1),l=a(null),u=a(t);return i(()=>{u.current=t}),i(()=>{let t=e.current,r=l.current;if(n||!t||!r)return;let i=!1,a=()=>{c.current||(c.current=!0,s(!0),u.current().catch(()=>null).finally(()=>{i||(c.current=!1,s(!1),o.unobserve(r),o.observe(r))}))},o=new IntersectionObserver(([e])=>{e.isIntersecting&&a()},{root:t});return o.observe(r),()=>{i=!0,o.disconnect()}},[e,n]),{isLoading:r,sentinelRef:l}}function m(e,t){let i=a(null),o=a(-1),s=a(null);return{containerRef:i,onKeyDown:r(r=>{let a=i.current;if(!a)return;let c=n.Children.toArray(e);if(c.length===0)return;let l=o.current;if(r.key===`ArrowDown`)r.preventDefault(),l=f(l,1,c.length);else if(r.key===`ArrowUp`)r.preventDefault(),l=f(l,-1,c.length);else if(r.key.length===1){let e=r.key.toLowerCase(),t=s.current===r.key?l+1:0,n=t=>d(t).toLowerCase().startsWith(e),i=c.slice(t).findIndex(n),a=i===-1?c.slice(0,t).findIndex(n):t+i;if(s.current=r.key,a===-1)return;l=a}else return;s.current=r.key,o.current=l;let u=a.children[l];if(u){let e=u.offsetTop,t=e+u.offsetHeight;e<a.scrollTop?a.scrollTop=e:t>a.scrollTop+a.clientHeight&&(a.scrollTop=t-a.clientHeight)}t(l)},[e,t])}}function h({children:n,onScroll:r,className:i=``,style:a,isDataLoading:o=!1,setHighlightedIndex:d=()=>null}){let{containerRef:f,onKeyDown:h}=m(n,d),{isLoading:g,sentinelRef:_}=p(f,r,o);return l(`div`,{className:s(t.infiniteBlock,i),style:a,onKeyDown:h,tabIndex:0,ref:f,children:o?l(`div`,{className:t.spinnerWrapper,children:l(e,{className:t.spinner})}):u(c,{children:[n,l(`div`,{ref:_,className:t.sentinel,"aria-hidden":`true`}),g&&l(`div`,{className:t.spinnerWrapper,children:l(e,{className:t.spinner})})]})})}export{h as default};
|
|
2
2
|
//# sourceMappingURL=infiniteBlock.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"infiniteBlock.mjs","names":[],"sources":["../../../../package/common/infiniteBlock/infiniteBlock.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\n\nimport styles from './infiniteBlock.module.pcss';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport type { InfiniteBlockProps } from './infiniteBlock.types';\n\n// Flattens a React node down to the text it renders, so keyboard type-ahead can match\n// against whatever a child actually displays — a plain string, a number, or something\n// wrapped in nested elements/fragments/arrays (e.g. an icon + label pair).\nfunction getNodeText(node: React.ReactNode): string {\n if (node === null || node === undefined || typeof node === 'boolean') return '';\n if (typeof node === 'string' || typeof node === 'number') return String(node);\n if (Array.isArray(node)) return node.map(getNodeText).join('');\n if (React.isValidElement<{ children?: React.ReactNode }>(node)) {\n return getNodeText(node.props.children);\n }\n return '';\n}\n\n// Cycles the index by `change`, wrapping directly from last to first (and first to last) —\n// no \"nothing highlighted\" stop in between, in either direction. `-1` means nothing is\n// highlighted yet: ArrowDown from there starts at the first item, ArrowUp at the last.\nfunction clampIndex(index: number, change: number, length: number): number {\n if (index === -1) return change > 0 ? 0 : length - 1;\n return (index + change + length) % length;\n}\n\n// Loads more items once a sentinel element at the end of the list scrolls into view.\n// IntersectionObserver only fires on a change of intersection state, so if a page of\n// freshly-loaded items still doesn't fill the container, the sentinel stays visible and\n// we have to re-arm the observer ourselves to pick up the next page.\nfunction useInfiniteScroll(\n containerRef: React.RefObject<HTMLDivElement | null>,\n onScroll: () => Promise<void>,\n disabled: boolean,\n) {\n const [isLoading, setIsLoading] = useState(false);\n const isLoadingRef = useRef(false);\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n // Kept in a ref so a caller passing a fresh onScroll function each render doesn't\n // tear down and recreate the observer every time.\n const onScrollRef = useRef(onScroll);\n useEffect(() => {\n onScrollRef.current = onScroll;\n });\n\n useEffect(() => {\n const root = containerRef.current;\n const sentinel = sentinelRef.current;\n if (disabled || !root || !sentinel) return undefined;\n\n let cancelled = false;\n\n const loadMore = () => {\n if (isLoadingRef.current) return;\n isLoadingRef.current = true;\n setIsLoading(true);\n\n onScrollRef\n .current()\n .catch(() => null)\n .finally(() => {\n if (cancelled) return;\n isLoadingRef.current = false;\n setIsLoading(false);\n observer.unobserve(sentinel);\n observer.observe(sentinel);\n });\n };\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) loadMore();\n },\n { root },\n );\n\n observer.observe(sentinel);\n\n return () => {\n cancelled = true;\n observer.disconnect();\n };\n }, [containerRef, disabled]);\n\n return { isLoading, sentinelRef };\n}\n\n// Arrow-key navigation plus type-ahead: pressing a character key jumps to the next child\n// whose text starts with it, cycling through repeats and wrapping at the end of the list.\nfunction useTypeaheadNav(children: React.ReactNode, setHighlightedIndex: (index: number) => void) {\n const containerRef = useRef<HTMLDivElement>(null);\n const indexRef = useRef(-1);\n const lastKeyRef = useRef<string | null>(null);\n\n const onKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n const container = containerRef.current;\n if (!container) return;\n\n const childArray = React.Children.toArray(children);\n if (childArray.length === 0) return;\n\n let index = indexRef.current;\n\n if (event.key === 'ArrowDown') {\n // Without this, the browser's own native \"scroll a focused scrollable element on\n // arrow keys\" behavior fires alongside our scrollIntoView math below, stacking an\n // extra native scroll on top of ours on every press until the highlighted item is\n // pushed out of view entirely.\n event.preventDefault();\n index = clampIndex(index, 1, childArray.length);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n index = clampIndex(index, -1, childArray.length);\n } else if (event.key.length === 1) {\n const key = event.key.toLowerCase();\n const repeatingKey = lastKeyRef.current === event.key;\n const searchStart = repeatingKey ? index + 1 : 0;\n const startsWithKey = (child: React.ReactNode) => getNodeText(child).toLowerCase().startsWith(key);\n\n const afterCurrent = childArray.slice(searchStart).findIndex(startsWithKey);\n const match =\n afterCurrent !== -1 ? searchStart + afterCurrent : childArray.slice(0, searchStart).findIndex(startsWithKey);\n\n lastKeyRef.current = event.key;\n if (match === -1) return;\n index = match;\n } else {\n return;\n }\n\n lastKeyRef.current = event.key;\n indexRef.current = index;\n\n const child = container.children[index] as HTMLElement | undefined;\n if (child) {\n const childTop = child.offsetTop;\n const childBottom = childTop + child.offsetHeight;\n if (childTop < container.scrollTop) {\n container.scrollTop = childTop;\n } else if (childBottom > container.scrollTop + container.clientHeight) {\n container.scrollTop = childBottom - container.clientHeight;\n }\n }\n setHighlightedIndex(index);\n },\n [children, setHighlightedIndex],\n );\n\n return { containerRef, onKeyDown };\n}\n\nfunction InfiniteBlock({\n children,\n onScroll,\n className = '',\n isDataLoading = false,\n setHighlightedIndex = () => null,\n}: InfiniteBlockProps) {\n const { containerRef, onKeyDown } = useTypeaheadNav(children, setHighlightedIndex);\n const { isLoading: showScrollSpinner, sentinelRef } = useInfiniteScroll(containerRef, onScroll, isDataLoading);\n\n return (\n <div
|
|
1
|
+
{"version":3,"file":"infiniteBlock.mjs","names":[],"sources":["../../../../package/common/infiniteBlock/infiniteBlock.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\n\nimport styles from './infiniteBlock.module.pcss';\nimport SpinnerLoading from '../loading/spinnerLoading';\nimport type { InfiniteBlockProps } from './infiniteBlock.types';\n\n// Flattens a React node down to the text it renders, so keyboard type-ahead can match\n// against whatever a child actually displays — a plain string, a number, or something\n// wrapped in nested elements/fragments/arrays (e.g. an icon + label pair).\nfunction getNodeText(node: React.ReactNode): string {\n if (node === null || node === undefined || typeof node === 'boolean') return '';\n if (typeof node === 'string' || typeof node === 'number') return String(node);\n if (Array.isArray(node)) return node.map(getNodeText).join('');\n if (React.isValidElement<{ children?: React.ReactNode }>(node)) {\n return getNodeText(node.props.children);\n }\n return '';\n}\n\n// Cycles the index by `change`, wrapping directly from last to first (and first to last) —\n// no \"nothing highlighted\" stop in between, in either direction. `-1` means nothing is\n// highlighted yet: ArrowDown from there starts at the first item, ArrowUp at the last.\nfunction clampIndex(index: number, change: number, length: number): number {\n if (index === -1) return change > 0 ? 0 : length - 1;\n return (index + change + length) % length;\n}\n\n// Loads more items once a sentinel element at the end of the list scrolls into view.\n// IntersectionObserver only fires on a change of intersection state, so if a page of\n// freshly-loaded items still doesn't fill the container, the sentinel stays visible and\n// we have to re-arm the observer ourselves to pick up the next page.\nfunction useInfiniteScroll(\n containerRef: React.RefObject<HTMLDivElement | null>,\n onScroll: () => Promise<void>,\n disabled: boolean,\n) {\n const [isLoading, setIsLoading] = useState(false);\n const isLoadingRef = useRef(false);\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n // Kept in a ref so a caller passing a fresh onScroll function each render doesn't\n // tear down and recreate the observer every time.\n const onScrollRef = useRef(onScroll);\n useEffect(() => {\n onScrollRef.current = onScroll;\n });\n\n useEffect(() => {\n const root = containerRef.current;\n const sentinel = sentinelRef.current;\n if (disabled || !root || !sentinel) return undefined;\n\n let cancelled = false;\n\n const loadMore = () => {\n if (isLoadingRef.current) return;\n isLoadingRef.current = true;\n setIsLoading(true);\n\n onScrollRef\n .current()\n .catch(() => null)\n .finally(() => {\n if (cancelled) return;\n isLoadingRef.current = false;\n setIsLoading(false);\n observer.unobserve(sentinel);\n observer.observe(sentinel);\n });\n };\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) loadMore();\n },\n { root },\n );\n\n observer.observe(sentinel);\n\n return () => {\n cancelled = true;\n observer.disconnect();\n };\n }, [containerRef, disabled]);\n\n return { isLoading, sentinelRef };\n}\n\n// Arrow-key navigation plus type-ahead: pressing a character key jumps to the next child\n// whose text starts with it, cycling through repeats and wrapping at the end of the list.\nfunction useTypeaheadNav(children: React.ReactNode, setHighlightedIndex: (index: number) => void) {\n const containerRef = useRef<HTMLDivElement>(null);\n const indexRef = useRef(-1);\n const lastKeyRef = useRef<string | null>(null);\n\n const onKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n const container = containerRef.current;\n if (!container) return;\n\n const childArray = React.Children.toArray(children);\n if (childArray.length === 0) return;\n\n let index = indexRef.current;\n\n if (event.key === 'ArrowDown') {\n // Without this, the browser's own native \"scroll a focused scrollable element on\n // arrow keys\" behavior fires alongside our scrollIntoView math below, stacking an\n // extra native scroll on top of ours on every press until the highlighted item is\n // pushed out of view entirely.\n event.preventDefault();\n index = clampIndex(index, 1, childArray.length);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n index = clampIndex(index, -1, childArray.length);\n } else if (event.key.length === 1) {\n const key = event.key.toLowerCase();\n const repeatingKey = lastKeyRef.current === event.key;\n const searchStart = repeatingKey ? index + 1 : 0;\n const startsWithKey = (child: React.ReactNode) => getNodeText(child).toLowerCase().startsWith(key);\n\n const afterCurrent = childArray.slice(searchStart).findIndex(startsWithKey);\n const match =\n afterCurrent !== -1 ? searchStart + afterCurrent : childArray.slice(0, searchStart).findIndex(startsWithKey);\n\n lastKeyRef.current = event.key;\n if (match === -1) return;\n index = match;\n } else {\n return;\n }\n\n lastKeyRef.current = event.key;\n indexRef.current = index;\n\n const child = container.children[index] as HTMLElement | undefined;\n if (child) {\n const childTop = child.offsetTop;\n const childBottom = childTop + child.offsetHeight;\n if (childTop < container.scrollTop) {\n container.scrollTop = childTop;\n } else if (childBottom > container.scrollTop + container.clientHeight) {\n container.scrollTop = childBottom - container.clientHeight;\n }\n }\n setHighlightedIndex(index);\n },\n [children, setHighlightedIndex],\n );\n\n return { containerRef, onKeyDown };\n}\n\nfunction InfiniteBlock({\n children,\n onScroll,\n className = '',\n style,\n isDataLoading = false,\n setHighlightedIndex = () => null,\n}: InfiniteBlockProps) {\n const { containerRef, onKeyDown } = useTypeaheadNav(children, setHighlightedIndex);\n const { isLoading: showScrollSpinner, sentinelRef } = useInfiniteScroll(containerRef, onScroll, isDataLoading);\n\n return (\n <div\n className={cx(styles.infiniteBlock, className)}\n style={style}\n onKeyDown={onKeyDown}\n tabIndex={0}\n ref={containerRef}\n >\n {isDataLoading ? (\n <div className={styles.spinnerWrapper}>\n <SpinnerLoading className={styles.spinner} />\n </div>\n ) : (\n <>\n {children}\n <div ref={sentinelRef} className={styles.sentinel} aria-hidden='true' />\n {showScrollSpinner && (\n <div className={styles.spinnerWrapper}>\n <SpinnerLoading className={styles.spinner} />\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n\nexport default InfiniteBlock;\n"],"mappings":"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"}
|