@dr.pogodin/react-utils 1.48.0 → 1.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useEffect","useMemo","useRef","createPortal","useTheme","defaultTheme","S","jsx","_jsx","jsxs","_jsxs","BaseModal","cancelOnScrolling","children","containerStyle","dontDisableScrolling","onCancel","overlayStyle","style","testId","testIdForOverlay","theme","containerRef","overlayRef","window","addEventListener","removeEventListener","document","body","classList","add","scrollingDisabledByModal","remove","focusLast","onFocus","elems","current","querySelectorAll","i","length","focus","activeElement","tabIndex","className","overlay","process","env","NODE_ENV","undefined","onClick","e","stopPropagation","onKeyDown","key","ref","node","role","container","onWheel","event","Modal","rest","composed"],"sources":["../../../../../src/shared/components/Modal/index.tsx"],"sourcesContent":["import {\n type CSSProperties,\n type FunctionComponent,\n type ReactNode,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './base-theme.scss';\nimport S from './styles.scss';\n\ntype ThemeT = Theme<'container' | 'overlay'>;\n\ntype PropsT = {\n cancelOnScrolling?: boolean;\n children?: ReactNode;\n dontDisableScrolling?: boolean;\n onCancel?: () => void;\n overlayStyle?: CSSProperties;\n style?: CSSProperties;\n testId?: string;\n testIdForOverlay?: string;\n theme: ThemeT;\n\n /** @deprecated */\n containerStyle?: CSSProperties;\n};\n\n/**\n * The `<Modal>` component implements a simple themeable modal window, wrapped\n * into the default theme. `<BaseModal>` exposes the base non-themed component.\n * **Children:** Component children are rendered as the modal content.\n * @param {object} props Component properties. Beside props documented below,\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties) are supported as well.\n * @param {function} [props.onCancel] The callback to trigger when user\n * clicks outside the modal, or presses Escape. It is expected to hide the\n * modal.\n * @param {ModalTheme} [props.theme] _Ad hoc_ theme.\n */\nconst BaseModal: FunctionComponent<PropsT> = ({\n cancelOnScrolling,\n children,\n containerStyle,\n dontDisableScrolling,\n onCancel,\n overlayStyle,\n style,\n testId,\n testIdForOverlay,\n theme,\n}) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n\n // Sets up modal cancellation of scrolling, if opted-in.\n useEffect(() => {\n if (cancelOnScrolling && onCancel) {\n window.addEventListener('scroll', onCancel);\n window.addEventListener('wheel', onCancel);\n }\n return () => {\n if (cancelOnScrolling && onCancel) {\n window.removeEventListener('scroll', onCancel);\n window.removeEventListener('wheel', onCancel);\n }\n };\n }, [cancelOnScrolling, onCancel]);\n\n // Disables window scrolling, if it is not opted-out.\n useEffect(() => {\n if (!dontDisableScrolling) {\n document.body.classList.add(S.scrollingDisabledByModal);\n }\n return () => {\n if (!dontDisableScrolling) {\n document.body.classList.remove(S.scrollingDisabledByModal);\n }\n };\n }, [dontDisableScrolling]);\n\n const focusLast = useMemo(() => (\n <div\n onFocus={() => {\n const elems = containerRef.current!.querySelectorAll('*');\n for (let i = elems.length - 1; i >= 0; --i) {\n (elems[i] as HTMLElement).focus();\n if (document.activeElement === elems[i]) return;\n }\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n ), []);\n\n return createPortal(\n (\n <div>\n {focusLast}\n <div\n aria-label=\"Cancel\"\n className={theme.overlay}\n data-testid={\n process.env.NODE_ENV === 'production'\n ? undefined : testIdForOverlay\n }\n onClick={(e) => {\n if (onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n onKeyDown={(e) => {\n if (e.key === 'Escape' && onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n ref={(node) => {\n if (node && node !== overlayRef.current) {\n overlayRef.current = node;\n node.focus();\n }\n }}\n role=\"button\"\n style={overlayStyle}\n tabIndex={0}\n />\n {\n // NOTE: These rules are disabled because our intention is to keep\n // the element non-interactive (thus not on the keyboard focus chain),\n // and it has `onClick` handler merely to stop propagation of click\n // events to its parent container. This is needed because, for example\n // when the modal is wrapped into an interactive element we don't want\n // any clicks inside the modal to bubble-up to that parent element\n // (because visually and logically the modal dialog does not belong\n // to its parent container, where it technically belongs from\n // the HTML mark-up perpective).\n }\n <div // eslint-disable-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n aria-modal=\"true\"\n className={theme.container}\n data-testid={process.env.NODE_ENV === 'production' ? undefined : testId}\n onClick={(e) => {\n e.stopPropagation();\n }}\n onWheel={(event) => {\n event.stopPropagation();\n }}\n ref={containerRef}\n role=\"dialog\"\n style={style ?? containerStyle}\n >\n {children}\n </div>\n <div\n onFocus={() => {\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n {focusLast}\n </div>\n ),\n document.body,\n );\n};\n\n/* Non-themed version of the Modal. */\nexport { BaseModal };\n\nconst Modal: FunctionComponent<\n Omit<PropsT, 'theme'> & { theme: ThemeT | undefined }\n> = ({ theme, ...rest }) => {\n const composed = useTheme('Modal', defaultTheme, theme);\n\n // eslint-disable-next-line react/jsx-props-no-spreading\n return <BaseModal {...rest} theme={composed} />;\n};\n\nexport default Modal;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useEffect","useMemo","useRef","createPortal","useTheme","defaultTheme","S","jsx","_jsx","jsxs","_jsxs","BaseModal","cancelOnScrolling","children","containerStyle","dontDisableScrolling","onCancel","overlayStyle","style","testId","testIdForOverlay","theme","containerRef","overlayRef","window","addEventListener","removeEventListener","document","body","classList","add","scrollingDisabledByModal","remove","focusLast","onFocus","elems","current","querySelectorAll","i","length","focus","activeElement","tabIndex","className","overlay","process","env","NODE_ENV","undefined","onClick","e","stopPropagation","onKeyDown","key","ref","node","role","container","onWheel","event","Modal","rest","composed"],"sources":["../../../../../src/shared/components/Modal/index.tsx"],"sourcesContent":["import {\n type CSSProperties,\n type FunctionComponent,\n type ReactNode,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './base-theme.scss';\nimport S from './styles.scss';\n\ntype ThemeT = Theme<'container' | 'overlay'>;\n\ntype PropsT = {\n cancelOnScrolling?: boolean;\n children?: ReactNode;\n dontDisableScrolling?: boolean;\n onCancel?: () => void;\n overlayStyle?: CSSProperties;\n style?: CSSProperties;\n testId?: string;\n testIdForOverlay?: string;\n theme: ThemeT;\n\n /** @deprecated */\n containerStyle?: CSSProperties;\n};\n\n/**\n * The `<Modal>` component implements a simple themeable modal window, wrapped\n * into the default theme. `<BaseModal>` exposes the base non-themed component.\n * **Children:** Component children are rendered as the modal content.\n * @param {object} props Component properties. Beside props documented below,\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties) are supported as well.\n * @param {function} [props.onCancel] The callback to trigger when user\n * clicks outside the modal, or presses Escape. It is expected to hide the\n * modal.\n * @param {ModalTheme} [props.theme] _Ad hoc_ theme.\n */\nconst BaseModal: FunctionComponent<PropsT> = ({\n cancelOnScrolling,\n children,\n containerStyle,\n dontDisableScrolling,\n onCancel,\n overlayStyle,\n style,\n testId,\n testIdForOverlay,\n theme,\n}) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n\n // Sets up modal cancellation of scrolling, if opted-in.\n useEffect(() => {\n if (cancelOnScrolling && onCancel) {\n window.addEventListener('scroll', onCancel);\n window.addEventListener('wheel', onCancel);\n }\n return () => {\n if (cancelOnScrolling && onCancel) {\n window.removeEventListener('scroll', onCancel);\n window.removeEventListener('wheel', onCancel);\n }\n };\n }, [cancelOnScrolling, onCancel]);\n\n // Disables window scrolling, if it is not opted-out.\n useEffect(() => {\n if (!dontDisableScrolling) {\n document.body.classList.add(S.scrollingDisabledByModal);\n }\n return () => {\n if (!dontDisableScrolling) {\n document.body.classList.remove(S.scrollingDisabledByModal);\n }\n };\n }, [dontDisableScrolling]);\n\n const focusLast = useMemo(() => (\n <div\n onFocus={() => {\n const elems = containerRef.current!.querySelectorAll('*');\n for (let i = elems.length - 1; i >= 0; --i) {\n (elems[i] as HTMLElement).focus();\n if (document.activeElement === elems[i]) return;\n }\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n ), []);\n\n return createPortal(\n (\n <div>\n {focusLast}\n <div\n aria-label=\"Cancel\"\n className={theme.overlay}\n data-testid={\n process.env.NODE_ENV === 'production'\n ? undefined : testIdForOverlay\n }\n onClick={(e) => {\n if (onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n onKeyDown={(e) => {\n if (e.key === 'Escape' && onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n ref={(node) => {\n if (node && node !== overlayRef.current) {\n overlayRef.current = node;\n node.focus();\n }\n }}\n role=\"button\"\n style={overlayStyle}\n tabIndex={0}\n />\n {\n // NOTE: These rules are disabled because our intention is to keep\n // the element non-interactive (thus not on the keyboard focus chain),\n // and it has `onClick` handler merely to stop propagation of click\n // events to its parent container. This is needed because, for example\n // when the modal is wrapped into an interactive element we don't want\n // any clicks inside the modal to bubble-up to that parent element\n // (because visually and logically the modal dialog does not belong\n // to its parent container, where it technically belongs from\n // the HTML mark-up perpective).\n }\n <div // eslint-disable-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n aria-modal=\"true\"\n className={theme.container}\n data-testid={process.env.NODE_ENV === 'production' ? undefined : testId}\n onClick={(e) => {\n e.stopPropagation();\n }}\n onWheel={(event) => {\n event.stopPropagation();\n }}\n ref={containerRef}\n role=\"dialog\"\n style={style ?? containerStyle}\n >\n {children}\n </div>\n <div\n onFocus={() => {\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n {focusLast}\n </div>\n ),\n document.body,\n );\n};\n\n/* Non-themed version of the Modal. */\nexport { BaseModal };\n\nconst Modal: FunctionComponent<\n Omit<PropsT, 'theme'> & { theme?: ThemeT }\n> = ({ theme, ...rest }) => {\n const composed = useTheme('Modal', defaultTheme, theme);\n\n // eslint-disable-next-line react/jsx-props-no-spreading\n return <BaseModal {...rest} theme={composed} />;\n};\n\nexport default Modal;\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","names":["isValue","x","type","optionValueName","option","value","name"],"sources":["../../../../../src/shared/components/selectors/common.ts"],"sourcesContent":["// The stuff common between different dropdown implementations.\n\nimport type { Theme } from '@dr.pogodin/react-themes';\n\nexport type ThemeT = Theme<\n | 'active'\n | 'arrow'\n | 'container'\n | 'dropdown'\n | 'hiddenOption'\n | 'label'\n | 'option'\n | 'select'\n\n // TODO: This is currently only valid for (native) <Dropdown>,\n // other kinds of selectors should be evaluated, and aligned with this\n // feature, if appropriate.\n | 'invalid'\n\n // TODO: This is only valid for <CustomDropdown>, thus we need to re-factor it\n // into a separate theme spec for that component.\n | 'upward'\n>;\n\nexport type ValueT = number | string;\n\nexport type OptionT<NameT> = {\n name?: NameT | null;\n value: ValueT;\n};\n\nexport type OptionsT<NameT> = Readonly<Array<OptionT<NameT> | ValueT>>;\n\nexport type PropsT<\n NameT,\n OnChangeT = React.ChangeEventHandler<HTMLSelectElement>,\n> = {\n filter?: (item: OptionT<NameT> | ValueT) => boolean;\n label?: React.ReactNode;\n onChange?: OnChangeT;\n options: Readonly<OptionsT<NameT>>;\n testId?: string;\n theme: ThemeT;\n value?: ValueT;\n};\n\nfunction isValue<T>(x: OptionT<T> | ValueT): x is ValueT {\n const type = typeof x;\n return type === 'number' || type === 'string';\n}\n\n/** Returns option value and name as a tuple. */\nexport function optionValueName<NameT>(\n option: OptionT<NameT> | ValueT,\n): [ValueT, NameT | ValueT] {\n return isValue(option)\n ? [option, option]\n : [option.value, option.name ?? option.value];\n}\n"],"mappings":"AAAA;;AA8CA,SAASA,OAAOA,CAAIC,CAAsB,EAAe;EACvD,MAAMC,IAAI,GAAG,OAAOD,CAAC;EACrB,OAAOC,IAAI,KAAK,QAAQ,IAAIA,IAAI,KAAK,QAAQ;AAC/C;;AAEA;AACA,OAAO,SAASC,eAAeA,CAC7BC,MAA+B,EACL;EAC1B,OAAOJ,OAAO,CAACI,MAAM,CAAC,GAClB,CAACA,MAAM,EAAEA,MAAM,CAAC,GAChB,CAACA,MAAM,CAACC,KAAK,EAAED,MAAM,CAACE,IAAI,IAAIF,MAAM,CAACC,KAAK,CAAC;AACjD","ignoreList":[]}
1
+ {"version":3,"file":"common.js","names":["isValue","x","type","optionValueName","option","value","name"],"sources":["../../../../../src/shared/components/selectors/common.ts"],"sourcesContent":["// The stuff common between different dropdown implementations.\n\nimport type { Theme } from '@dr.pogodin/react-themes';\n\nexport type ThemeT = Theme<\n | 'active'\n | 'arrow'\n | 'container'\n | 'dropdown'\n | 'hiddenOption'\n | 'label'\n | 'option'\n | 'select'\n\n // TODO: This is currently only valid for (native) <Dropdown>,\n // other kinds of selectors should be evaluated, and aligned with this\n // feature, if appropriate.\n | 'invalid'\n\n // TODO: This is only valid for <CustomDropdown>, thus we need to re-factor it\n // into a separate theme spec for that component.\n | 'upward'\n>;\n\nexport type ValueT = number | string;\n\nexport type OptionT<NameT> = {\n name?: NameT | null;\n value: ValueT;\n};\n\nexport type OptionsT<NameT> = Readonly<Array<OptionT<NameT> | ValueT>>;\n\nexport type PropsT<\n NameT,\n OnChangeT = React.ChangeEventHandler<HTMLSelectElement>,\n> = {\n filter?: (item: OptionT<NameT> | ValueT) => boolean;\n label?: React.ReactNode;\n onChange?: OnChangeT;\n options: Readonly<OptionsT<NameT>>;\n testId?: string;\n theme?: ThemeT;\n value?: ValueT;\n};\n\nfunction isValue<T>(x: OptionT<T> | ValueT): x is ValueT {\n const type = typeof x;\n return type === 'number' || type === 'string';\n}\n\n/** Returns option value and name as a tuple. */\nexport function optionValueName<NameT>(\n option: OptionT<NameT> | ValueT,\n): [ValueT, NameT | ValueT] {\n return isValue(option)\n ? [option, option]\n : [option.value, option.name ?? option.value];\n}\n"],"mappings":"AAAA;;AA8CA,SAASA,OAAOA,CAAIC,CAAsB,EAAe;EACvD,MAAMC,IAAI,GAAG,OAAOD,CAAC;EACrB,OAAOC,IAAI,KAAK,QAAQ,IAAIA,IAAI,KAAK,QAAQ;AAC/C;;AAEA;AACA,OAAO,SAASC,eAAeA,CAC7BC,MAA+B,EACL;EAC1B,OAAOJ,OAAO,CAACI,MAAM,CAAC,GAClB,CAACA,MAAM,EAAEA,MAAM,CAAC,GAChB,CAACA,MAAM,CAACC,KAAK,EAAED,MAAM,CAACE,IAAI,IAAIF,MAAM,CAACC,KAAK,CAAC;AACjD","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useEffect","useMemo","useRef","createPortal","useTheme","defaultTheme","S","jsx","_jsx","jsxs","_jsxs","BaseModal","cancelOnScrolling","children","containerStyle","dontDisableScrolling","onCancel","overlayStyle","style","testId","testIdForOverlay","theme","containerRef","overlayRef","window","addEventListener","removeEventListener","document","body","classList","add","scrollingDisabledByModal","remove","focusLast","onFocus","elems","current","querySelectorAll","i","length","focus","activeElement","tabIndex","className","overlay","process","env","NODE_ENV","undefined","onClick","e","stopPropagation","onKeyDown","key","ref","node","role","container","onWheel","event","Modal","rest","composed"],"sources":["../../../../../src/shared/components/Modal/index.tsx"],"sourcesContent":["import {\n type CSSProperties,\n type FunctionComponent,\n type ReactNode,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './base-theme.scss';\nimport S from './styles.scss';\n\ntype ThemeT = Theme<'container' | 'overlay'>;\n\ntype PropsT = {\n cancelOnScrolling?: boolean;\n children?: ReactNode;\n dontDisableScrolling?: boolean;\n onCancel?: () => void;\n overlayStyle?: CSSProperties;\n style?: CSSProperties;\n testId?: string;\n testIdForOverlay?: string;\n theme: ThemeT;\n\n /** @deprecated */\n containerStyle?: CSSProperties;\n};\n\n/**\n * The `<Modal>` component implements a simple themeable modal window, wrapped\n * into the default theme. `<BaseModal>` exposes the base non-themed component.\n * **Children:** Component children are rendered as the modal content.\n * @param {object} props Component properties. Beside props documented below,\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties) are supported as well.\n * @param {function} [props.onCancel] The callback to trigger when user\n * clicks outside the modal, or presses Escape. It is expected to hide the\n * modal.\n * @param {ModalTheme} [props.theme] _Ad hoc_ theme.\n */\nconst BaseModal: FunctionComponent<PropsT> = ({\n cancelOnScrolling,\n children,\n containerStyle,\n dontDisableScrolling,\n onCancel,\n overlayStyle,\n style,\n testId,\n testIdForOverlay,\n theme,\n}) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n\n // Sets up modal cancellation of scrolling, if opted-in.\n useEffect(() => {\n if (cancelOnScrolling && onCancel) {\n window.addEventListener('scroll', onCancel);\n window.addEventListener('wheel', onCancel);\n }\n return () => {\n if (cancelOnScrolling && onCancel) {\n window.removeEventListener('scroll', onCancel);\n window.removeEventListener('wheel', onCancel);\n }\n };\n }, [cancelOnScrolling, onCancel]);\n\n // Disables window scrolling, if it is not opted-out.\n useEffect(() => {\n if (!dontDisableScrolling) {\n document.body.classList.add(S.scrollingDisabledByModal);\n }\n return () => {\n if (!dontDisableScrolling) {\n document.body.classList.remove(S.scrollingDisabledByModal);\n }\n };\n }, [dontDisableScrolling]);\n\n const focusLast = useMemo(() => (\n <div\n onFocus={() => {\n const elems = containerRef.current!.querySelectorAll('*');\n for (let i = elems.length - 1; i >= 0; --i) {\n (elems[i] as HTMLElement).focus();\n if (document.activeElement === elems[i]) return;\n }\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n ), []);\n\n return createPortal(\n (\n <div>\n {focusLast}\n <div\n aria-label=\"Cancel\"\n className={theme.overlay}\n data-testid={\n process.env.NODE_ENV === 'production'\n ? undefined : testIdForOverlay\n }\n onClick={(e) => {\n if (onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n onKeyDown={(e) => {\n if (e.key === 'Escape' && onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n ref={(node) => {\n if (node && node !== overlayRef.current) {\n overlayRef.current = node;\n node.focus();\n }\n }}\n role=\"button\"\n style={overlayStyle}\n tabIndex={0}\n />\n {\n // NOTE: These rules are disabled because our intention is to keep\n // the element non-interactive (thus not on the keyboard focus chain),\n // and it has `onClick` handler merely to stop propagation of click\n // events to its parent container. This is needed because, for example\n // when the modal is wrapped into an interactive element we don't want\n // any clicks inside the modal to bubble-up to that parent element\n // (because visually and logically the modal dialog does not belong\n // to its parent container, where it technically belongs from\n // the HTML mark-up perpective).\n }\n <div // eslint-disable-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n aria-modal=\"true\"\n className={theme.container}\n data-testid={process.env.NODE_ENV === 'production' ? undefined : testId}\n onClick={(e) => {\n e.stopPropagation();\n }}\n onWheel={(event) => {\n event.stopPropagation();\n }}\n ref={containerRef}\n role=\"dialog\"\n style={style ?? containerStyle}\n >\n {children}\n </div>\n <div\n onFocus={() => {\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n {focusLast}\n </div>\n ),\n document.body,\n );\n};\n\n/* Non-themed version of the Modal. */\nexport { BaseModal };\n\nconst Modal: FunctionComponent<\n Omit<PropsT, 'theme'> & { theme: ThemeT | undefined }\n> = ({ theme, ...rest }) => {\n const composed = useTheme('Modal', defaultTheme, theme);\n\n // eslint-disable-next-line react/jsx-props-no-spreading\n return <BaseModal {...rest} theme={composed} />;\n};\n\nexport default Modal;\n"],"mappings":"AAAA,OAIEA,SAAS,CACTC,OAAO,CACPC,MAAM,KACD,OAAO,CAEd,OAASC,YAAY,KAAQ,WAAW,CACxC,OAAqBC,QAAQ,KAAQ,0BAA0B,OAAAC,YAAA,iGAAAC,CAAA,uCAGjC,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAmB9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACA,KAAM,CAAAC,SAAoC,CAAGA,CAAC,CAC5CC,iBAAiB,CACjBC,QAAQ,CACRC,cAAc,CACdC,oBAAoB,CACpBC,QAAQ,CACRC,YAAY,CACZC,KAAK,CACLC,MAAM,CACNC,gBAAgB,CAChBC,KACF,CAAC,GAAK,CACJ,KAAM,CAAAC,YAAY,CAAGpB,MAAM,CAAwB,IAAI,CAAC,CACxD,KAAM,CAAAqB,UAAU,CAAGrB,MAAM,CAAwB,IAAI,CAAC,CAEtD;AACAF,SAAS,CAAC,IAAM,CACd,GAAIY,iBAAiB,EAAII,QAAQ,CAAE,CACjCQ,MAAM,CAACC,gBAAgB,CAAC,QAAQ,CAAET,QAAQ,CAAC,CAC3CQ,MAAM,CAACC,gBAAgB,CAAC,OAAO,CAAET,QAAQ,CAC3C,CACA,MAAO,IAAM,CACX,GAAIJ,iBAAiB,EAAII,QAAQ,CAAE,CACjCQ,MAAM,CAACE,mBAAmB,CAAC,QAAQ,CAAEV,QAAQ,CAAC,CAC9CQ,MAAM,CAACE,mBAAmB,CAAC,OAAO,CAAEV,QAAQ,CAC9C,CACF,CACF,CAAC,CAAE,CAACJ,iBAAiB,CAAEI,QAAQ,CAAC,CAAC,CAEjC;AACAhB,SAAS,CAAC,IAAM,CACd,GAAI,CAACe,oBAAoB,CAAE,CACzBY,QAAQ,CAACC,IAAI,CAACC,SAAS,CAACC,GAAG,CAACxB,CAAC,CAACyB,wBAAwB,CACxD,CACA,MAAO,IAAM,CACX,GAAI,CAAChB,oBAAoB,CAAE,CACzBY,QAAQ,CAACC,IAAI,CAACC,SAAS,CAACG,MAAM,CAAC1B,CAAC,CAACyB,wBAAwB,CAC3D,CACF,CACF,CAAC,CAAE,CAAChB,oBAAoB,CAAC,CAAC,CAE1B,KAAM,CAAAkB,SAAS,CAAGhC,OAAO,CAAC,iBACxBO,IAAA,QACE0B,OAAO,CAAEA,CAAA,GAAM,CACb,KAAM,CAAAC,KAAK,CAAGb,YAAY,CAACc,OAAO,CAAEC,gBAAgB,CAAC,GAAG,CAAC,CACzD,IAAK,GAAI,CAAAC,CAAC,CAAGH,KAAK,CAACI,MAAM,CAAG,CAAC,CAAED,CAAC,EAAI,CAAC,CAAE,EAAEA,CAAC,CAAE,CACzCH,KAAK,CAACG,CAAC,CAAC,CAAiBE,KAAK,CAAC,CAAC,CACjC,GAAIb,QAAQ,CAACc,aAAa,GAAKN,KAAK,CAACG,CAAC,CAAC,CAAE,MAC3C,CACAf,UAAU,CAACa,OAAO,EAAEI,KAAK,CAAC,CAC5B,CACA;AACA;AAAA,CACAE,QAAQ,CAAE,CAAE,CACb,CACF,CAAE,EAAE,CAAC,CAEN,mBAAOvC,YAAY,cAEfO,KAAA,QAAAG,QAAA,EACGoB,SAAS,cACVzB,IAAA,QACE,aAAW,QAAQ,CACnBmC,SAAS,CAAEtB,KAAK,CAACuB,OAAQ,CACzB,cACEC,OAAO,CAACC,GAAG,CAACC,QAAQ,GAAK,YAAY,CACjCC,SAAS,CAAG5B,gBACjB,CACD6B,OAAO,CAAGC,CAAC,EAAK,CACd,GAAIlC,QAAQ,CAAE,CACZA,QAAQ,CAAC,CAAC,CACVkC,CAAC,CAACC,eAAe,CAAC,CACpB,CACF,CAAE,CACFC,SAAS,CAAGF,CAAC,EAAK,CAChB,GAAIA,CAAC,CAACG,GAAG,GAAK,QAAQ,EAAIrC,QAAQ,CAAE,CAClCA,QAAQ,CAAC,CAAC,CACVkC,CAAC,CAACC,eAAe,CAAC,CACpB,CACF,CAAE,CACFG,GAAG,CAAGC,IAAI,EAAK,CACb,GAAIA,IAAI,EAAIA,IAAI,GAAKhC,UAAU,CAACa,OAAO,CAAE,CACvCb,UAAU,CAACa,OAAO,CAAGmB,IAAI,CACzBA,IAAI,CAACf,KAAK,CAAC,CACb,CACF,CAAE,CACFgB,IAAI,CAAC,QAAQ,CACbtC,KAAK,CAAED,YAAa,CACpByB,QAAQ,CAAE,CAAE,CACb,CAAC,cAYFlC,IAAA,QAAK;AACH,aAAW,MAAM,CACjBmC,SAAS,CAAEtB,KAAK,CAACoC,SAAU,CAC3B,cAAaZ,OAAO,CAACC,GAAG,CAACC,QAAQ,GAAK,YAAY,CAAGC,SAAS,CAAG7B,MAAO,CACxE8B,OAAO,CAAGC,CAAC,EAAK,CACdA,CAAC,CAACC,eAAe,CAAC,CACpB,CAAE,CACFO,OAAO,CAAGC,KAAK,EAAK,CAClBA,KAAK,CAACR,eAAe,CAAC,CACxB,CAAE,CACFG,GAAG,CAAEhC,YAAa,CAClBkC,IAAI,CAAC,QAAQ,CACbtC,KAAK,CAAEA,KAAK,EAAIJ,cAAe,CAAAD,QAAA,CAE9BA,QAAQ,CACN,CAAC,cACNL,IAAA,QACE0B,OAAO,CAAEA,CAAA,GAAM,CACbX,UAAU,CAACa,OAAO,EAAEI,KAAK,CAAC,CAC5B,CACA;AACA;AAAA,CACAE,QAAQ,CAAE,CAAE,CACb,CAAC,CACDT,SAAS,EACP,CAAC,CAERN,QAAQ,CAACC,IACX,CACF,CAAC,CAED,sCACA,OAASjB,SAAS,EAElB,KAAM,CAAAiD,KAEL,CAAGA,CAAC,CAAEvC,KAAK,CAAE,GAAGwC,IAAK,CAAC,GAAK,CAC1B,KAAM,CAAAC,QAAQ,CAAG1D,QAAQ,CAAC,OAAO,CAAEC,YAAY,CAAEgB,KAAK,CAAC,CAEvD;AACA,mBAAOb,IAAA,CAACG,SAAS,KAAKkD,IAAI,CAAExC,KAAK,CAAEyC,QAAS,CAAE,CAChD,CAAC,CAED,cAAe,CAAAF,KAAK","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useEffect","useMemo","useRef","createPortal","useTheme","defaultTheme","S","jsx","_jsx","jsxs","_jsxs","BaseModal","cancelOnScrolling","children","containerStyle","dontDisableScrolling","onCancel","overlayStyle","style","testId","testIdForOverlay","theme","containerRef","overlayRef","window","addEventListener","removeEventListener","document","body","classList","add","scrollingDisabledByModal","remove","focusLast","onFocus","elems","current","querySelectorAll","i","length","focus","activeElement","tabIndex","className","overlay","process","env","NODE_ENV","undefined","onClick","e","stopPropagation","onKeyDown","key","ref","node","role","container","onWheel","event","Modal","rest","composed"],"sources":["../../../../../src/shared/components/Modal/index.tsx"],"sourcesContent":["import {\n type CSSProperties,\n type FunctionComponent,\n type ReactNode,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './base-theme.scss';\nimport S from './styles.scss';\n\ntype ThemeT = Theme<'container' | 'overlay'>;\n\ntype PropsT = {\n cancelOnScrolling?: boolean;\n children?: ReactNode;\n dontDisableScrolling?: boolean;\n onCancel?: () => void;\n overlayStyle?: CSSProperties;\n style?: CSSProperties;\n testId?: string;\n testIdForOverlay?: string;\n theme: ThemeT;\n\n /** @deprecated */\n containerStyle?: CSSProperties;\n};\n\n/**\n * The `<Modal>` component implements a simple themeable modal window, wrapped\n * into the default theme. `<BaseModal>` exposes the base non-themed component.\n * **Children:** Component children are rendered as the modal content.\n * @param {object} props Component properties. Beside props documented below,\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties) are supported as well.\n * @param {function} [props.onCancel] The callback to trigger when user\n * clicks outside the modal, or presses Escape. It is expected to hide the\n * modal.\n * @param {ModalTheme} [props.theme] _Ad hoc_ theme.\n */\nconst BaseModal: FunctionComponent<PropsT> = ({\n cancelOnScrolling,\n children,\n containerStyle,\n dontDisableScrolling,\n onCancel,\n overlayStyle,\n style,\n testId,\n testIdForOverlay,\n theme,\n}) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n\n // Sets up modal cancellation of scrolling, if opted-in.\n useEffect(() => {\n if (cancelOnScrolling && onCancel) {\n window.addEventListener('scroll', onCancel);\n window.addEventListener('wheel', onCancel);\n }\n return () => {\n if (cancelOnScrolling && onCancel) {\n window.removeEventListener('scroll', onCancel);\n window.removeEventListener('wheel', onCancel);\n }\n };\n }, [cancelOnScrolling, onCancel]);\n\n // Disables window scrolling, if it is not opted-out.\n useEffect(() => {\n if (!dontDisableScrolling) {\n document.body.classList.add(S.scrollingDisabledByModal);\n }\n return () => {\n if (!dontDisableScrolling) {\n document.body.classList.remove(S.scrollingDisabledByModal);\n }\n };\n }, [dontDisableScrolling]);\n\n const focusLast = useMemo(() => (\n <div\n onFocus={() => {\n const elems = containerRef.current!.querySelectorAll('*');\n for (let i = elems.length - 1; i >= 0; --i) {\n (elems[i] as HTMLElement).focus();\n if (document.activeElement === elems[i]) return;\n }\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n ), []);\n\n return createPortal(\n (\n <div>\n {focusLast}\n <div\n aria-label=\"Cancel\"\n className={theme.overlay}\n data-testid={\n process.env.NODE_ENV === 'production'\n ? undefined : testIdForOverlay\n }\n onClick={(e) => {\n if (onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n onKeyDown={(e) => {\n if (e.key === 'Escape' && onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n ref={(node) => {\n if (node && node !== overlayRef.current) {\n overlayRef.current = node;\n node.focus();\n }\n }}\n role=\"button\"\n style={overlayStyle}\n tabIndex={0}\n />\n {\n // NOTE: These rules are disabled because our intention is to keep\n // the element non-interactive (thus not on the keyboard focus chain),\n // and it has `onClick` handler merely to stop propagation of click\n // events to its parent container. This is needed because, for example\n // when the modal is wrapped into an interactive element we don't want\n // any clicks inside the modal to bubble-up to that parent element\n // (because visually and logically the modal dialog does not belong\n // to its parent container, where it technically belongs from\n // the HTML mark-up perpective).\n }\n <div // eslint-disable-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n aria-modal=\"true\"\n className={theme.container}\n data-testid={process.env.NODE_ENV === 'production' ? undefined : testId}\n onClick={(e) => {\n e.stopPropagation();\n }}\n onWheel={(event) => {\n event.stopPropagation();\n }}\n ref={containerRef}\n role=\"dialog\"\n style={style ?? containerStyle}\n >\n {children}\n </div>\n <div\n onFocus={() => {\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n {focusLast}\n </div>\n ),\n document.body,\n );\n};\n\n/* Non-themed version of the Modal. */\nexport { BaseModal };\n\nconst Modal: FunctionComponent<\n Omit<PropsT, 'theme'> & { theme?: ThemeT }\n> = ({ theme, ...rest }) => {\n const composed = useTheme('Modal', defaultTheme, theme);\n\n // eslint-disable-next-line react/jsx-props-no-spreading\n return <BaseModal {...rest} theme={composed} />;\n};\n\nexport default Modal;\n"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","names":["isValue","x","type","optionValueName","option","value","name"],"sources":["../../../../../src/shared/components/selectors/common.ts"],"sourcesContent":["// The stuff common between different dropdown implementations.\n\nimport type { Theme } from '@dr.pogodin/react-themes';\n\nexport type ThemeT = Theme<\n | 'active'\n | 'arrow'\n | 'container'\n | 'dropdown'\n | 'hiddenOption'\n | 'label'\n | 'option'\n | 'select'\n\n // TODO: This is currently only valid for (native) <Dropdown>,\n // other kinds of selectors should be evaluated, and aligned with this\n // feature, if appropriate.\n | 'invalid'\n\n // TODO: This is only valid for <CustomDropdown>, thus we need to re-factor it\n // into a separate theme spec for that component.\n | 'upward'\n>;\n\nexport type ValueT = number | string;\n\nexport type OptionT<NameT> = {\n name?: NameT | null;\n value: ValueT;\n};\n\nexport type OptionsT<NameT> = Readonly<Array<OptionT<NameT> | ValueT>>;\n\nexport type PropsT<\n NameT,\n OnChangeT = React.ChangeEventHandler<HTMLSelectElement>,\n> = {\n filter?: (item: OptionT<NameT> | ValueT) => boolean;\n label?: React.ReactNode;\n onChange?: OnChangeT;\n options: Readonly<OptionsT<NameT>>;\n testId?: string;\n theme: ThemeT;\n value?: ValueT;\n};\n\nfunction isValue<T>(x: OptionT<T> | ValueT): x is ValueT {\n const type = typeof x;\n return type === 'number' || type === 'string';\n}\n\n/** Returns option value and name as a tuple. */\nexport function optionValueName<NameT>(\n option: OptionT<NameT> | ValueT,\n): [ValueT, NameT | ValueT] {\n return isValue(option)\n ? [option, option]\n : [option.value, option.name ?? option.value];\n}\n"],"mappings":"AAAA;AA8CA,QAAS,CAAAA,OAAOA,CAAIC,CAAsB,CAAe,CACvD,KAAM,CAAAC,IAAI,CAAG,MAAO,CAAAD,CAAC,CACrB,MAAO,CAAAC,IAAI,GAAK,QAAQ,EAAIA,IAAI,GAAK,QACvC,CAEA,gDACA,MAAO,SAAS,CAAAC,eAAeA,CAC7BC,MAA+B,CACL,CAC1B,MAAO,CAAAJ,OAAO,CAACI,MAAM,CAAC,CAClB,CAACA,MAAM,CAAEA,MAAM,CAAC,CAChB,CAACA,MAAM,CAACC,KAAK,CAAED,MAAM,CAACE,IAAI,EAAIF,MAAM,CAACC,KAAK,CAChD","ignoreList":[]}
1
+ {"version":3,"file":"common.js","names":["isValue","x","type","optionValueName","option","value","name"],"sources":["../../../../../src/shared/components/selectors/common.ts"],"sourcesContent":["// The stuff common between different dropdown implementations.\n\nimport type { Theme } from '@dr.pogodin/react-themes';\n\nexport type ThemeT = Theme<\n | 'active'\n | 'arrow'\n | 'container'\n | 'dropdown'\n | 'hiddenOption'\n | 'label'\n | 'option'\n | 'select'\n\n // TODO: This is currently only valid for (native) <Dropdown>,\n // other kinds of selectors should be evaluated, and aligned with this\n // feature, if appropriate.\n | 'invalid'\n\n // TODO: This is only valid for <CustomDropdown>, thus we need to re-factor it\n // into a separate theme spec for that component.\n | 'upward'\n>;\n\nexport type ValueT = number | string;\n\nexport type OptionT<NameT> = {\n name?: NameT | null;\n value: ValueT;\n};\n\nexport type OptionsT<NameT> = Readonly<Array<OptionT<NameT> | ValueT>>;\n\nexport type PropsT<\n NameT,\n OnChangeT = React.ChangeEventHandler<HTMLSelectElement>,\n> = {\n filter?: (item: OptionT<NameT> | ValueT) => boolean;\n label?: React.ReactNode;\n onChange?: OnChangeT;\n options: Readonly<OptionsT<NameT>>;\n testId?: string;\n theme?: ThemeT;\n value?: ValueT;\n};\n\nfunction isValue<T>(x: OptionT<T> | ValueT): x is ValueT {\n const type = typeof x;\n return type === 'number' || type === 'string';\n}\n\n/** Returns option value and name as a tuple. */\nexport function optionValueName<NameT>(\n option: OptionT<NameT> | ValueT,\n): [ValueT, NameT | ValueT] {\n return isValue(option)\n ? [option, option]\n : [option.value, option.name ?? option.value];\n}\n"],"mappings":"AAAA;AA8CA,QAAS,CAAAA,OAAOA,CAAIC,CAAsB,CAAe,CACvD,KAAM,CAAAC,IAAI,CAAG,MAAO,CAAAD,CAAC,CACrB,MAAO,CAAAC,IAAI,GAAK,QAAQ,EAAIA,IAAI,GAAK,QACvC,CAEA,gDACA,MAAO,SAAS,CAAAC,eAAeA,CAC7BC,MAA+B,CACL,CAC1B,MAAO,CAAAJ,OAAO,CAACI,MAAM,CAAC,CAClB,CAACA,MAAM,CAAEA,MAAM,CAAC,CAChB,CAACA,MAAM,CAACC,KAAK,CAAED,MAAM,CAACE,IAAI,EAAIF,MAAM,CAACC,KAAK,CAChD","ignoreList":[]}
@@ -28,6 +28,6 @@ type PropsT = {
28
28
  declare const BaseModal: FunctionComponent<PropsT>;
29
29
  export { BaseModal };
30
30
  declare const Modal: FunctionComponent<Omit<PropsT, 'theme'> & {
31
- theme: ThemeT | undefined;
31
+ theme?: ThemeT;
32
32
  }>;
33
33
  export default Modal;
@@ -12,7 +12,7 @@ export type PropsT<NameT, OnChangeT = React.ChangeEventHandler<HTMLSelectElement
12
12
  onChange?: OnChangeT;
13
13
  options: Readonly<OptionsT<NameT>>;
14
14
  testId?: string;
15
- theme: ThemeT;
15
+ theme?: ThemeT;
16
16
  value?: ValueT;
17
17
  };
18
18
  /** Returns option value and name as a tuple. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useEffect","useMemo","useRef","createPortal","useTheme","defaultTheme","S","jsx","_jsx","jsxs","_jsxs","BaseModal","cancelOnScrolling","children","containerStyle","dontDisableScrolling","onCancel","overlayStyle","style","testId","testIdForOverlay","theme","containerRef","overlayRef","window","addEventListener","removeEventListener","document","body","classList","add","scrollingDisabledByModal","remove","focusLast","onFocus","elems","current","querySelectorAll","i","length","focus","activeElement","tabIndex","className","overlay","process","env","NODE_ENV","undefined","onClick","e","stopPropagation","onKeyDown","key","ref","node","role","container","onWheel","event","Modal","rest","composed"],"sources":["../../../../../src/shared/components/Modal/index.tsx"],"sourcesContent":["import {\n type CSSProperties,\n type FunctionComponent,\n type ReactNode,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './base-theme.scss';\nimport S from './styles.scss';\n\ntype ThemeT = Theme<'container' | 'overlay'>;\n\ntype PropsT = {\n cancelOnScrolling?: boolean;\n children?: ReactNode;\n dontDisableScrolling?: boolean;\n onCancel?: () => void;\n overlayStyle?: CSSProperties;\n style?: CSSProperties;\n testId?: string;\n testIdForOverlay?: string;\n theme: ThemeT;\n\n /** @deprecated */\n containerStyle?: CSSProperties;\n};\n\n/**\n * The `<Modal>` component implements a simple themeable modal window, wrapped\n * into the default theme. `<BaseModal>` exposes the base non-themed component.\n * **Children:** Component children are rendered as the modal content.\n * @param {object} props Component properties. Beside props documented below,\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties) are supported as well.\n * @param {function} [props.onCancel] The callback to trigger when user\n * clicks outside the modal, or presses Escape. It is expected to hide the\n * modal.\n * @param {ModalTheme} [props.theme] _Ad hoc_ theme.\n */\nconst BaseModal: FunctionComponent<PropsT> = ({\n cancelOnScrolling,\n children,\n containerStyle,\n dontDisableScrolling,\n onCancel,\n overlayStyle,\n style,\n testId,\n testIdForOverlay,\n theme,\n}) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n\n // Sets up modal cancellation of scrolling, if opted-in.\n useEffect(() => {\n if (cancelOnScrolling && onCancel) {\n window.addEventListener('scroll', onCancel);\n window.addEventListener('wheel', onCancel);\n }\n return () => {\n if (cancelOnScrolling && onCancel) {\n window.removeEventListener('scroll', onCancel);\n window.removeEventListener('wheel', onCancel);\n }\n };\n }, [cancelOnScrolling, onCancel]);\n\n // Disables window scrolling, if it is not opted-out.\n useEffect(() => {\n if (!dontDisableScrolling) {\n document.body.classList.add(S.scrollingDisabledByModal);\n }\n return () => {\n if (!dontDisableScrolling) {\n document.body.classList.remove(S.scrollingDisabledByModal);\n }\n };\n }, [dontDisableScrolling]);\n\n const focusLast = useMemo(() => (\n <div\n onFocus={() => {\n const elems = containerRef.current!.querySelectorAll('*');\n for (let i = elems.length - 1; i >= 0; --i) {\n (elems[i] as HTMLElement).focus();\n if (document.activeElement === elems[i]) return;\n }\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n ), []);\n\n return createPortal(\n (\n <div>\n {focusLast}\n <div\n aria-label=\"Cancel\"\n className={theme.overlay}\n data-testid={\n process.env.NODE_ENV === 'production'\n ? undefined : testIdForOverlay\n }\n onClick={(e) => {\n if (onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n onKeyDown={(e) => {\n if (e.key === 'Escape' && onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n ref={(node) => {\n if (node && node !== overlayRef.current) {\n overlayRef.current = node;\n node.focus();\n }\n }}\n role=\"button\"\n style={overlayStyle}\n tabIndex={0}\n />\n {\n // NOTE: These rules are disabled because our intention is to keep\n // the element non-interactive (thus not on the keyboard focus chain),\n // and it has `onClick` handler merely to stop propagation of click\n // events to its parent container. This is needed because, for example\n // when the modal is wrapped into an interactive element we don't want\n // any clicks inside the modal to bubble-up to that parent element\n // (because visually and logically the modal dialog does not belong\n // to its parent container, where it technically belongs from\n // the HTML mark-up perpective).\n }\n <div // eslint-disable-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n aria-modal=\"true\"\n className={theme.container}\n data-testid={process.env.NODE_ENV === 'production' ? undefined : testId}\n onClick={(e) => {\n e.stopPropagation();\n }}\n onWheel={(event) => {\n event.stopPropagation();\n }}\n ref={containerRef}\n role=\"dialog\"\n style={style ?? containerStyle}\n >\n {children}\n </div>\n <div\n onFocus={() => {\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n {focusLast}\n </div>\n ),\n document.body,\n );\n};\n\n/* Non-themed version of the Modal. */\nexport { BaseModal };\n\nconst Modal: FunctionComponent<\n Omit<PropsT, 'theme'> & { theme: ThemeT | undefined }\n> = ({ theme, ...rest }) => {\n const composed = useTheme('Modal', defaultTheme, theme);\n\n // eslint-disable-next-line react/jsx-props-no-spreading\n return <BaseModal {...rest} theme={composed} />;\n};\n\nexport default Modal;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useEffect","useMemo","useRef","createPortal","useTheme","defaultTheme","S","jsx","_jsx","jsxs","_jsxs","BaseModal","cancelOnScrolling","children","containerStyle","dontDisableScrolling","onCancel","overlayStyle","style","testId","testIdForOverlay","theme","containerRef","overlayRef","window","addEventListener","removeEventListener","document","body","classList","add","scrollingDisabledByModal","remove","focusLast","onFocus","elems","current","querySelectorAll","i","length","focus","activeElement","tabIndex","className","overlay","process","env","NODE_ENV","undefined","onClick","e","stopPropagation","onKeyDown","key","ref","node","role","container","onWheel","event","Modal","rest","composed"],"sources":["../../../../../src/shared/components/Modal/index.tsx"],"sourcesContent":["import {\n type CSSProperties,\n type FunctionComponent,\n type ReactNode,\n useEffect,\n useMemo,\n useRef,\n} from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './base-theme.scss';\nimport S from './styles.scss';\n\ntype ThemeT = Theme<'container' | 'overlay'>;\n\ntype PropsT = {\n cancelOnScrolling?: boolean;\n children?: ReactNode;\n dontDisableScrolling?: boolean;\n onCancel?: () => void;\n overlayStyle?: CSSProperties;\n style?: CSSProperties;\n testId?: string;\n testIdForOverlay?: string;\n theme: ThemeT;\n\n /** @deprecated */\n containerStyle?: CSSProperties;\n};\n\n/**\n * The `<Modal>` component implements a simple themeable modal window, wrapped\n * into the default theme. `<BaseModal>` exposes the base non-themed component.\n * **Children:** Component children are rendered as the modal content.\n * @param {object} props Component properties. Beside props documented below,\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties) are supported as well.\n * @param {function} [props.onCancel] The callback to trigger when user\n * clicks outside the modal, or presses Escape. It is expected to hide the\n * modal.\n * @param {ModalTheme} [props.theme] _Ad hoc_ theme.\n */\nconst BaseModal: FunctionComponent<PropsT> = ({\n cancelOnScrolling,\n children,\n containerStyle,\n dontDisableScrolling,\n onCancel,\n overlayStyle,\n style,\n testId,\n testIdForOverlay,\n theme,\n}) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n\n // Sets up modal cancellation of scrolling, if opted-in.\n useEffect(() => {\n if (cancelOnScrolling && onCancel) {\n window.addEventListener('scroll', onCancel);\n window.addEventListener('wheel', onCancel);\n }\n return () => {\n if (cancelOnScrolling && onCancel) {\n window.removeEventListener('scroll', onCancel);\n window.removeEventListener('wheel', onCancel);\n }\n };\n }, [cancelOnScrolling, onCancel]);\n\n // Disables window scrolling, if it is not opted-out.\n useEffect(() => {\n if (!dontDisableScrolling) {\n document.body.classList.add(S.scrollingDisabledByModal);\n }\n return () => {\n if (!dontDisableScrolling) {\n document.body.classList.remove(S.scrollingDisabledByModal);\n }\n };\n }, [dontDisableScrolling]);\n\n const focusLast = useMemo(() => (\n <div\n onFocus={() => {\n const elems = containerRef.current!.querySelectorAll('*');\n for (let i = elems.length - 1; i >= 0; --i) {\n (elems[i] as HTMLElement).focus();\n if (document.activeElement === elems[i]) return;\n }\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n ), []);\n\n return createPortal(\n (\n <div>\n {focusLast}\n <div\n aria-label=\"Cancel\"\n className={theme.overlay}\n data-testid={\n process.env.NODE_ENV === 'production'\n ? undefined : testIdForOverlay\n }\n onClick={(e) => {\n if (onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n onKeyDown={(e) => {\n if (e.key === 'Escape' && onCancel) {\n onCancel();\n e.stopPropagation();\n }\n }}\n ref={(node) => {\n if (node && node !== overlayRef.current) {\n overlayRef.current = node;\n node.focus();\n }\n }}\n role=\"button\"\n style={overlayStyle}\n tabIndex={0}\n />\n {\n // NOTE: These rules are disabled because our intention is to keep\n // the element non-interactive (thus not on the keyboard focus chain),\n // and it has `onClick` handler merely to stop propagation of click\n // events to its parent container. This is needed because, for example\n // when the modal is wrapped into an interactive element we don't want\n // any clicks inside the modal to bubble-up to that parent element\n // (because visually and logically the modal dialog does not belong\n // to its parent container, where it technically belongs from\n // the HTML mark-up perpective).\n }\n <div // eslint-disable-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n aria-modal=\"true\"\n className={theme.container}\n data-testid={process.env.NODE_ENV === 'production' ? undefined : testId}\n onClick={(e) => {\n e.stopPropagation();\n }}\n onWheel={(event) => {\n event.stopPropagation();\n }}\n ref={containerRef}\n role=\"dialog\"\n style={style ?? containerStyle}\n >\n {children}\n </div>\n <div\n onFocus={() => {\n overlayRef.current?.focus();\n }}\n // TODO: Have a look at this later.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n />\n {focusLast}\n </div>\n ),\n document.body,\n );\n};\n\n/* Non-themed version of the Modal. */\nexport { BaseModal };\n\nconst Modal: FunctionComponent<\n Omit<PropsT, 'theme'> & { theme?: ThemeT }\n> = ({ theme, ...rest }) => {\n const composed = useTheme('Modal', defaultTheme, theme);\n\n // eslint-disable-next-line react/jsx-props-no-spreading\n return <BaseModal {...rest} theme={composed} />;\n};\n\nexport default Modal;\n"],"mappings":"AAAA,SAIEA,SAAS,EACTC,OAAO,EACPC,MAAM,QACD,OAAO;AAEd,SAASC,YAAY,QAAQ,WAAW;AACxC,SAAqBC,QAAQ,QAAQ,0BAA0B;AAE/D,OAAOC,YAAY;AACnB,OAAOC,CAAC;AAAsB,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAmB9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,SAAoC,GAAGA,CAAC;EAC5CC,iBAAiB;EACjBC,QAAQ;EACRC,cAAc;EACdC,oBAAoB;EACpBC,QAAQ;EACRC,YAAY;EACZC,KAAK;EACLC,MAAM;EACNC,gBAAgB;EAChBC;AACF,CAAC,KAAK;EACJ,MAAMC,YAAY,GAAGpB,MAAM,CAAwB,IAAI,CAAC;EACxD,MAAMqB,UAAU,GAAGrB,MAAM,CAAwB,IAAI,CAAC;;EAEtD;EACAF,SAAS,CAAC,MAAM;IACd,IAAIY,iBAAiB,IAAII,QAAQ,EAAE;MACjCQ,MAAM,CAACC,gBAAgB,CAAC,QAAQ,EAAET,QAAQ,CAAC;MAC3CQ,MAAM,CAACC,gBAAgB,CAAC,OAAO,EAAET,QAAQ,CAAC;IAC5C;IACA,OAAO,MAAM;MACX,IAAIJ,iBAAiB,IAAII,QAAQ,EAAE;QACjCQ,MAAM,CAACE,mBAAmB,CAAC,QAAQ,EAAEV,QAAQ,CAAC;QAC9CQ,MAAM,CAACE,mBAAmB,CAAC,OAAO,EAAEV,QAAQ,CAAC;MAC/C;IACF,CAAC;EACH,CAAC,EAAE,CAACJ,iBAAiB,EAAEI,QAAQ,CAAC,CAAC;;EAEjC;EACAhB,SAAS,CAAC,MAAM;IACd,IAAI,CAACe,oBAAoB,EAAE;MACzBY,QAAQ,CAACC,IAAI,CAACC,SAAS,CAACC,GAAG,CAACxB,CAAC,CAACyB,wBAAwB,CAAC;IACzD;IACA,OAAO,MAAM;MACX,IAAI,CAAChB,oBAAoB,EAAE;QACzBY,QAAQ,CAACC,IAAI,CAACC,SAAS,CAACG,MAAM,CAAC1B,CAAC,CAACyB,wBAAwB,CAAC;MAC5D;IACF,CAAC;EACH,CAAC,EAAE,CAAChB,oBAAoB,CAAC,CAAC;EAE1B,MAAMkB,SAAS,GAAGhC,OAAO,CAAC,mBACxBO,IAAA;IACE0B,OAAO,EAAEA,CAAA,KAAM;MACb,MAAMC,KAAK,GAAGb,YAAY,CAACc,OAAO,CAAEC,gBAAgB,CAAC,GAAG,CAAC;MACzD,KAAK,IAAIC,CAAC,GAAGH,KAAK,CAACI,MAAM,GAAG,CAAC,EAAED,CAAC,IAAI,CAAC,EAAE,EAAEA,CAAC,EAAE;QACzCH,KAAK,CAACG,CAAC,CAAC,CAAiBE,KAAK,CAAC,CAAC;QACjC,IAAIb,QAAQ,CAACc,aAAa,KAAKN,KAAK,CAACG,CAAC,CAAC,EAAE;MAC3C;MACAf,UAAU,CAACa,OAAO,EAAEI,KAAK,CAAC,CAAC;IAC7B;IACA;IACA;IAAA;IACAE,QAAQ,EAAE;EAAE,CACb,CACF,EAAE,EAAE,CAAC;EAEN,oBAAOvC,YAAY,cAEfO,KAAA;IAAAG,QAAA,GACGoB,SAAS,eACVzB,IAAA;MACE,cAAW,QAAQ;MACnBmC,SAAS,EAAEtB,KAAK,CAACuB,OAAQ;MACzB,eACEC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,GACjCC,SAAS,GAAG5B,gBACjB;MACD6B,OAAO,EAAGC,CAAC,IAAK;QACd,IAAIlC,QAAQ,EAAE;UACZA,QAAQ,CAAC,CAAC;UACVkC,CAAC,CAACC,eAAe,CAAC,CAAC;QACrB;MACF,CAAE;MACFC,SAAS,EAAGF,CAAC,IAAK;QAChB,IAAIA,CAAC,CAACG,GAAG,KAAK,QAAQ,IAAIrC,QAAQ,EAAE;UAClCA,QAAQ,CAAC,CAAC;UACVkC,CAAC,CAACC,eAAe,CAAC,CAAC;QACrB;MACF,CAAE;MACFG,GAAG,EAAGC,IAAI,IAAK;QACb,IAAIA,IAAI,IAAIA,IAAI,KAAKhC,UAAU,CAACa,OAAO,EAAE;UACvCb,UAAU,CAACa,OAAO,GAAGmB,IAAI;UACzBA,IAAI,CAACf,KAAK,CAAC,CAAC;QACd;MACF,CAAE;MACFgB,IAAI,EAAC,QAAQ;MACbtC,KAAK,EAAED,YAAa;MACpByB,QAAQ,EAAE;IAAE,CACb,CAAC,eAYFlC,IAAA;MAAK;MACH,cAAW,MAAM;MACjBmC,SAAS,EAAEtB,KAAK,CAACoC,SAAU;MAC3B,eAAaZ,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,GAAGC,SAAS,GAAG7B,MAAO;MACxE8B,OAAO,EAAGC,CAAC,IAAK;QACdA,CAAC,CAACC,eAAe,CAAC,CAAC;MACrB,CAAE;MACFO,OAAO,EAAGC,KAAK,IAAK;QAClBA,KAAK,CAACR,eAAe,CAAC,CAAC;MACzB,CAAE;MACFG,GAAG,EAAEhC,YAAa;MAClBkC,IAAI,EAAC,QAAQ;MACbtC,KAAK,EAAEA,KAAK,IAAIJ,cAAe;MAAAD,QAAA,EAE9BA;IAAQ,CACN,CAAC,eACNL,IAAA;MACE0B,OAAO,EAAEA,CAAA,KAAM;QACbX,UAAU,CAACa,OAAO,EAAEI,KAAK,CAAC,CAAC;MAC7B;MACA;MACA;MAAA;MACAE,QAAQ,EAAE;IAAE,CACb,CAAC,EACDT,SAAS;EAAA,CACP,CAAC,EAERN,QAAQ,CAACC,IACX,CAAC;AACH,CAAC;;AAED;AACA,SAASjB,SAAS;AAElB,MAAMiD,KAEL,GAAGA,CAAC;EAAEvC,KAAK;EAAE,GAAGwC;AAAK,CAAC,KAAK;EAC1B,MAAMC,QAAQ,GAAG1D,QAAQ,CAAC,OAAO,EAAEC,YAAY,EAAEgB,KAAK,CAAC;;EAEvD;EACA,oBAAOb,IAAA,CAACG,SAAS;IAAA,GAAKkD,IAAI;IAAExC,KAAK,EAAEyC;EAAS,CAAE,CAAC;AACjD,CAAC;AAED,eAAeF,KAAK","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","names":["isValue","x","type","optionValueName","option","value","name"],"sources":["../../../../../src/shared/components/selectors/common.ts"],"sourcesContent":["// The stuff common between different dropdown implementations.\n\nimport type { Theme } from '@dr.pogodin/react-themes';\n\nexport type ThemeT = Theme<\n | 'active'\n | 'arrow'\n | 'container'\n | 'dropdown'\n | 'hiddenOption'\n | 'label'\n | 'option'\n | 'select'\n\n // TODO: This is currently only valid for (native) <Dropdown>,\n // other kinds of selectors should be evaluated, and aligned with this\n // feature, if appropriate.\n | 'invalid'\n\n // TODO: This is only valid for <CustomDropdown>, thus we need to re-factor it\n // into a separate theme spec for that component.\n | 'upward'\n>;\n\nexport type ValueT = number | string;\n\nexport type OptionT<NameT> = {\n name?: NameT | null;\n value: ValueT;\n};\n\nexport type OptionsT<NameT> = Readonly<Array<OptionT<NameT> | ValueT>>;\n\nexport type PropsT<\n NameT,\n OnChangeT = React.ChangeEventHandler<HTMLSelectElement>,\n> = {\n filter?: (item: OptionT<NameT> | ValueT) => boolean;\n label?: React.ReactNode;\n onChange?: OnChangeT;\n options: Readonly<OptionsT<NameT>>;\n testId?: string;\n theme: ThemeT;\n value?: ValueT;\n};\n\nfunction isValue<T>(x: OptionT<T> | ValueT): x is ValueT {\n const type = typeof x;\n return type === 'number' || type === 'string';\n}\n\n/** Returns option value and name as a tuple. */\nexport function optionValueName<NameT>(\n option: OptionT<NameT> | ValueT,\n): [ValueT, NameT | ValueT] {\n return isValue(option)\n ? [option, option]\n : [option.value, option.name ?? option.value];\n}\n"],"mappings":"AAAA;;AA8CA,SAASA,OAAOA,CAAIC,CAAsB,EAAe;EACvD,MAAMC,IAAI,GAAG,OAAOD,CAAC;EACrB,OAAOC,IAAI,KAAK,QAAQ,IAAIA,IAAI,KAAK,QAAQ;AAC/C;;AAEA;AACA,OAAO,SAASC,eAAeA,CAC7BC,MAA+B,EACL;EAC1B,OAAOJ,OAAO,CAACI,MAAM,CAAC,GAClB,CAACA,MAAM,EAAEA,MAAM,CAAC,GAChB,CAACA,MAAM,CAACC,KAAK,EAAED,MAAM,CAACE,IAAI,IAAIF,MAAM,CAACC,KAAK,CAAC;AACjD","ignoreList":[]}
1
+ {"version":3,"file":"common.js","names":["isValue","x","type","optionValueName","option","value","name"],"sources":["../../../../../src/shared/components/selectors/common.ts"],"sourcesContent":["// The stuff common between different dropdown implementations.\n\nimport type { Theme } from '@dr.pogodin/react-themes';\n\nexport type ThemeT = Theme<\n | 'active'\n | 'arrow'\n | 'container'\n | 'dropdown'\n | 'hiddenOption'\n | 'label'\n | 'option'\n | 'select'\n\n // TODO: This is currently only valid for (native) <Dropdown>,\n // other kinds of selectors should be evaluated, and aligned with this\n // feature, if appropriate.\n | 'invalid'\n\n // TODO: This is only valid for <CustomDropdown>, thus we need to re-factor it\n // into a separate theme spec for that component.\n | 'upward'\n>;\n\nexport type ValueT = number | string;\n\nexport type OptionT<NameT> = {\n name?: NameT | null;\n value: ValueT;\n};\n\nexport type OptionsT<NameT> = Readonly<Array<OptionT<NameT> | ValueT>>;\n\nexport type PropsT<\n NameT,\n OnChangeT = React.ChangeEventHandler<HTMLSelectElement>,\n> = {\n filter?: (item: OptionT<NameT> | ValueT) => boolean;\n label?: React.ReactNode;\n onChange?: OnChangeT;\n options: Readonly<OptionsT<NameT>>;\n testId?: string;\n theme?: ThemeT;\n value?: ValueT;\n};\n\nfunction isValue<T>(x: OptionT<T> | ValueT): x is ValueT {\n const type = typeof x;\n return type === 'number' || type === 'string';\n}\n\n/** Returns option value and name as a tuple. */\nexport function optionValueName<NameT>(\n option: OptionT<NameT> | ValueT,\n): [ValueT, NameT | ValueT] {\n return isValue(option)\n ? [option, option]\n : [option.value, option.name ?? option.value];\n}\n"],"mappings":"AAAA;;AA8CA,SAASA,OAAOA,CAAIC,CAAsB,EAAe;EACvD,MAAMC,IAAI,GAAG,OAAOD,CAAC;EACrB,OAAOC,IAAI,KAAK,QAAQ,IAAIA,IAAI,KAAK,QAAQ;AAC/C;;AAEA;AACA,OAAO,SAASC,eAAeA,CAC7BC,MAA+B,EACL;EAC1B,OAAOJ,OAAO,CAACI,MAAM,CAAC,GAClB,CAACA,MAAM,EAAEA,MAAM,CAAC,GAChB,CAACA,MAAM,CAACC,KAAK,EAAED,MAAM,CAACE,IAAI,IAAIF,MAAM,CAACC,KAAK,CAAC;AACjD","ignoreList":[]}
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.48.0",
2
+ "version": "1.48.1",
3
3
  "bin": {
4
4
  "react-utils-build": "bin/build.js",
5
5
  "react-utils-setup": "bin/setup.js"