@dr.pogodin/react-utils 1.47.4 → 1.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/build/development/client/getInj.js +4 -0
  2. package/build/development/client/getInj.js.map +1 -1
  3. package/build/development/index.js +1 -1
  4. package/build/development/index.js.map +1 -1
  5. package/build/development/server/server.js +0 -1
  6. package/build/development/server/server.js.map +1 -1
  7. package/build/development/shared/components/Button/index.js +13 -9
  8. package/build/development/shared/components/Button/index.js.map +1 -1
  9. package/build/development/shared/components/Checkbox/index.js +8 -7
  10. package/build/development/shared/components/Checkbox/index.js.map +1 -1
  11. package/build/development/shared/components/Input/index.js +14 -12
  12. package/build/development/shared/components/Input/index.js.map +1 -1
  13. package/build/development/shared/components/Modal/index.js +15 -3
  14. package/build/development/shared/components/Modal/index.js.map +1 -1
  15. package/build/development/shared/components/PageLayout/index.js +18 -15
  16. package/build/development/shared/components/PageLayout/index.js.map +1 -1
  17. package/build/development/shared/components/TextArea/index.js +9 -8
  18. package/build/development/shared/components/TextArea/index.js.map +1 -1
  19. package/build/development/shared/components/Throbber/index.js +15 -12
  20. package/build/development/shared/components/Throbber/index.js.map +1 -1
  21. package/build/development/shared/components/WithTooltip/index.js +6 -6
  22. package/build/development/shared/components/WithTooltip/index.js.map +1 -1
  23. package/build/development/shared/components/YouTubeVideo/index.js +6 -5
  24. package/build/development/shared/components/YouTubeVideo/index.js.map +1 -1
  25. package/build/development/shared/components/selectors/CustomDropdown/index.js +13 -12
  26. package/build/development/shared/components/selectors/CustomDropdown/index.js.map +1 -1
  27. package/build/development/shared/components/selectors/NativeDropdown/index.js +11 -10
  28. package/build/development/shared/components/selectors/NativeDropdown/index.js.map +1 -1
  29. package/build/development/shared/components/selectors/Switch/index.js +9 -9
  30. package/build/development/shared/components/selectors/Switch/index.js.map +1 -1
  31. package/build/development/shared/components/selectors/common.js.map +1 -1
  32. package/build/development/shared/components/selectors/index.js +1 -1
  33. package/build/development/shared/components/selectors/index.js.map +1 -1
  34. package/build/development/shared/utils/index.js +2 -5
  35. package/build/development/shared/utils/index.js.map +1 -1
  36. package/build/development/shared/utils/jest/E2eSsrEnv.js +0 -1
  37. package/build/development/shared/utils/jest/E2eSsrEnv.js.map +1 -1
  38. package/build/production/client/getInj.js +2 -2
  39. package/build/production/client/getInj.js.map +1 -1
  40. package/build/production/index.js +1 -1
  41. package/build/production/index.js.map +1 -1
  42. package/build/production/server/server.js +1 -1
  43. package/build/production/server/server.js.map +1 -1
  44. package/build/production/shared/components/Button/index.js +3 -8
  45. package/build/production/shared/components/Button/index.js.map +1 -1
  46. package/build/production/shared/components/Checkbox/index.js +1 -1
  47. package/build/production/shared/components/Checkbox/index.js.map +1 -1
  48. package/build/production/shared/components/Input/index.js +6 -6
  49. package/build/production/shared/components/Input/index.js.map +1 -1
  50. package/build/production/shared/components/Modal/index.js +3 -2
  51. package/build/production/shared/components/Modal/index.js.map +1 -1
  52. package/build/production/shared/components/PageLayout/index.js +2 -2
  53. package/build/production/shared/components/PageLayout/index.js.map +1 -1
  54. package/build/production/shared/components/TextArea/index.js +4 -4
  55. package/build/production/shared/components/TextArea/index.js.map +1 -1
  56. package/build/production/shared/components/Throbber/index.js +2 -2
  57. package/build/production/shared/components/Throbber/index.js.map +1 -1
  58. package/build/production/shared/components/WithTooltip/index.js +3 -3
  59. package/build/production/shared/components/WithTooltip/index.js.map +1 -1
  60. package/build/production/shared/components/YouTubeVideo/index.js +4 -4
  61. package/build/production/shared/components/YouTubeVideo/index.js.map +1 -1
  62. package/build/production/shared/components/selectors/CustomDropdown/index.js +2 -2
  63. package/build/production/shared/components/selectors/CustomDropdown/index.js.map +1 -1
  64. package/build/production/shared/components/selectors/NativeDropdown/index.js +3 -3
  65. package/build/production/shared/components/selectors/NativeDropdown/index.js.map +1 -1
  66. package/build/production/shared/components/selectors/Switch/index.js +1 -1
  67. package/build/production/shared/components/selectors/Switch/index.js.map +1 -1
  68. package/build/production/shared/components/selectors/common.js.map +1 -1
  69. package/build/production/shared/components/selectors/index.js +1 -1
  70. package/build/production/shared/components/selectors/index.js.map +1 -1
  71. package/build/production/shared/utils/index.js +1 -1
  72. package/build/production/shared/utils/index.js.map +1 -1
  73. package/build/production/shared/utils/jest/E2eSsrEnv.js +1 -1
  74. package/build/production/shared/utils/jest/E2eSsrEnv.js.map +1 -1
  75. package/build/types-code/index.d.ts +1 -1
  76. package/build/types-code/shared/components/Button/index.d.ts +6 -10
  77. package/build/types-code/shared/components/Checkbox/index.d.ts +4 -3
  78. package/build/types-code/shared/components/Input/index.d.ts +12 -4
  79. package/build/types-code/shared/components/Modal/index.d.ts +6 -3
  80. package/build/types-code/shared/components/PageLayout/index.d.ts +19 -4
  81. package/build/types-code/shared/components/TextArea/index.d.ts +4 -4
  82. package/build/types-code/shared/components/Throbber/index.d.ts +13 -3
  83. package/build/types-code/shared/components/WithTooltip/index.d.ts +18 -4
  84. package/build/types-code/shared/components/YouTubeVideo/index.d.ts +20 -4
  85. package/build/types-code/shared/components/selectors/CustomDropdown/index.d.ts +3 -2
  86. package/build/types-code/shared/components/selectors/NativeDropdown/index.d.ts +22 -2
  87. package/build/types-code/shared/components/selectors/Switch/index.d.ts +7 -6
  88. package/build/types-code/shared/components/selectors/common.d.ts +2 -3
  89. package/build/types-code/shared/components/selectors/index.d.ts +2 -2
  90. package/build/types-code/shared/utils/index.d.ts +2 -7
  91. package/build/web/client/getInj.js +3 -0
  92. package/build/web/client/getInj.js.map +1 -1
  93. package/build/web/index.js +1 -1
  94. package/build/web/index.js.map +1 -1
  95. package/build/web/server/server.js +0 -1
  96. package/build/web/server/server.js.map +1 -1
  97. package/build/web/shared/components/Button/index.js +13 -9
  98. package/build/web/shared/components/Button/index.js.map +1 -1
  99. package/build/web/shared/components/Checkbox/index.js +8 -7
  100. package/build/web/shared/components/Checkbox/index.js.map +1 -1
  101. package/build/web/shared/components/Input/index.js +14 -12
  102. package/build/web/shared/components/Input/index.js.map +1 -1
  103. package/build/web/shared/components/Modal/index.js +15 -3
  104. package/build/web/shared/components/Modal/index.js.map +1 -1
  105. package/build/web/shared/components/PageLayout/index.js +18 -15
  106. package/build/web/shared/components/PageLayout/index.js.map +1 -1
  107. package/build/web/shared/components/TextArea/index.js +9 -8
  108. package/build/web/shared/components/TextArea/index.js.map +1 -1
  109. package/build/web/shared/components/Throbber/index.js +15 -12
  110. package/build/web/shared/components/Throbber/index.js.map +1 -1
  111. package/build/web/shared/components/WithTooltip/index.js +6 -6
  112. package/build/web/shared/components/WithTooltip/index.js.map +1 -1
  113. package/build/web/shared/components/YouTubeVideo/index.js +6 -5
  114. package/build/web/shared/components/YouTubeVideo/index.js.map +1 -1
  115. package/build/web/shared/components/selectors/CustomDropdown/index.js +13 -12
  116. package/build/web/shared/components/selectors/CustomDropdown/index.js.map +1 -1
  117. package/build/web/shared/components/selectors/NativeDropdown/index.js +11 -10
  118. package/build/web/shared/components/selectors/NativeDropdown/index.js.map +1 -1
  119. package/build/web/shared/components/selectors/Switch/index.js +9 -9
  120. package/build/web/shared/components/selectors/Switch/index.js.map +1 -1
  121. package/build/web/shared/components/selectors/common.js.map +1 -1
  122. package/build/web/shared/components/selectors/index.js +1 -1
  123. package/build/web/shared/components/selectors/index.js.map +1 -1
  124. package/build/web/shared/utils/index.js +2 -5
  125. package/build/web/shared/utils/index.js.map +1 -1
  126. package/build/web/shared/utils/jest/E2eSsrEnv.js +0 -1
  127. package/build/web/shared/utils/jest/E2eSsrEnv.js.map +1 -1
  128. package/config/babel/webpack.js +1 -1
  129. package/package.json +15 -15
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useEffect","useMemo","useRef","createPortal","themed","baseTheme","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"],"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 themed, { type Theme } from '@dr.pogodin/react-themes';\n\nimport baseTheme from './base-theme.scss';\nimport S from './styles.scss';\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: Theme<'container' | 'overlay'>;\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\nexport default /* #__PURE__ */ themed(BaseModal, 'Modal', baseTheme);\n\n/* Non-themed version of the Modal. */\nexport { BaseModal };\n"],"mappings":"AAAA,OAIEA,SAAS,CACTC,OAAO,CACPC,MAAM,KACD,OAAO,CAEd,OAASC,YAAY,KAAQ,WAAW,CACxC,MAAO,CAAAC,MAAM,KAAsB,0BAA0B,OAAAC,SAAA,iGAAAC,CAAA,uCAG/B,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAiB9B;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,cAAe,eAAgBxB,MAAM,CAACO,SAAS,CAAE,OAAO,CAAEN,SAAS,CAAC,CAEpE,sCACA,OAASM,SAAS","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 | 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,4 +1,4 @@
1
- import themed from"@dr.pogodin/react-themes";const baseTheme={"context":"zv9tdn","ad":"yr8hbI","hoc":"_01Mz0J","container":"blPmpk","mainPanel":"zPoY0u","sidePanel":"mRD159"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";/**
1
+ import{useTheme}from"@dr.pogodin/react-themes";const baseTheme={"context":"zv9tdn","ad":"yr8hbI","hoc":"_01Mz0J","container":"blPmpk","mainPanel":"zPoY0u","sidePanel":"mRD159"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";/**
2
2
  * Simple and themeable page layout. It keeps the main content centered in
3
3
  * a column of limited width, which fills entire viewport on small screens
4
4
  * (under `$screen-md = 1024px` size). At larger screens the column keeps
@@ -12,5 +12,5 @@ import themed from"@dr.pogodin/react-themes";const baseTheme={"context":"zv9tdn"
12
12
  * @param {PageLayoutTheme} [props.theme] _Ad hoc_ theme.
13
13
  * @param {...any} [props....]
14
14
  * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)
15
- */const PageLayout=({children,leftSidePanelContent,rightSidePanelContent,theme})=>/*#__PURE__*/_jsxs("div",{className:theme.container,children:[/*#__PURE__*/_jsx("div",{className:[theme.sidePanel,theme.leftSidePanel].join(" "),children:leftSidePanelContent}),/*#__PURE__*/_jsx("div",{className:theme.mainPanel,children:children}),/*#__PURE__*/_jsx("div",{className:[theme.sidePanel,theme.rightSidePanel].join(" "),children:rightSidePanelContent})]});export default/* #__PURE__ */themed(PageLayout,"PageLayout",baseTheme);
15
+ */const PageLayout=({children,leftSidePanelContent,rightSidePanelContent,theme})=>{const composed=useTheme("PageLayout",baseTheme,theme);return/*#__PURE__*/_jsxs("div",{className:composed.container,children:[/*#__PURE__*/_jsx("div",{className:[composed.sidePanel,composed.leftSidePanel].join(" "),children:leftSidePanelContent}),/*#__PURE__*/_jsx("div",{className:composed.mainPanel,children:children}),/*#__PURE__*/_jsx("div",{className:[composed.sidePanel,composed.rightSidePanel].join(" "),children:rightSidePanelContent})]})};export default PageLayout;
16
16
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["themed","baseTheme","jsx","_jsx","jsxs","_jsxs","PageLayout","children","leftSidePanelContent","rightSidePanelContent","theme","className","container","sidePanel","leftSidePanel","join","mainPanel","rightSidePanel"],"sources":["../../../../../src/shared/components/PageLayout/index.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\n\nimport themed, { type Theme } from '@dr.pogodin/react-themes';\n\nimport baseTheme from './base-theme.scss';\n\ntype ThemeKeyT = 'container' | 'leftSidePanel' | 'mainPanel' | 'rightSidePanel'\n | 'sidePanel';\n\ntype PropsT = {\n children?: ReactNode;\n leftSidePanelContent?: ReactNode;\n rightSidePanelContent?: ReactNode;\n theme: Theme<ThemeKeyT>;\n};\n\n/**\n * Simple and themeable page layout. It keeps the main content centered in\n * a column of limited width, which fills entire viewport on small screens\n * (under `$screen-md = 1024px` size). At larger screens the column keeps\n * `$screen-md` size, and it is centered at the page, surrounded by side\n * panels, where additional content can be displayed.\n *\n * **Children:** Component children are rendered as the content of main panel.\n * @param {object} [props] Component properties.\n * @param {Node} [props.leftSidePanelContent] The content for left side panel.\n * @param {Node} [props.rightSidePanelContent] The content for right side panel.\n * @param {PageLayoutTheme} [props.theme] _Ad hoc_ theme.\n * @param {...any} [props....]\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)\n */\nconst PageLayout: React.FunctionComponent<PropsT> = ({\n children,\n leftSidePanelContent,\n rightSidePanelContent,\n theme,\n}) => (\n <div className={theme.container}>\n <div className={[theme.sidePanel, theme.leftSidePanel].join(' ')}>\n {leftSidePanelContent}\n </div>\n <div className={theme.mainPanel}>\n {children}\n </div>\n <div className={[theme.sidePanel, theme.rightSidePanel].join(' ')}>\n {rightSidePanelContent}\n </div>\n </div>\n);\n\nexport default /* #__PURE__ */ themed(PageLayout, 'PageLayout', baseTheme);\n"],"mappings":"AAEA,MAAO,CAAAA,MAAM,KAAsB,0BAA0B,OAAAC,SAAA,mHAEnB,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAY1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACA,KAAM,CAAAC,UAA2C,CAAGA,CAAC,CACnDC,QAAQ,CACRC,oBAAoB,CACpBC,qBAAqB,CACrBC,KACF,CAAC,gBACCL,KAAA,QAAKM,SAAS,CAAED,KAAK,CAACE,SAAU,CAAAL,QAAA,eAC9BJ,IAAA,QAAKQ,SAAS,CAAE,CAACD,KAAK,CAACG,SAAS,CAAEH,KAAK,CAACI,aAAa,CAAC,CAACC,IAAI,CAAC,GAAG,CAAE,CAAAR,QAAA,CAC9DC,oBAAoB,CAClB,CAAC,cACNL,IAAA,QAAKQ,SAAS,CAAED,KAAK,CAACM,SAAU,CAAAT,QAAA,CAC7BA,QAAQ,CACN,CAAC,cACNJ,IAAA,QAAKQ,SAAS,CAAE,CAACD,KAAK,CAACG,SAAS,CAAEH,KAAK,CAACO,cAAc,CAAC,CAACF,IAAI,CAAC,GAAG,CAAE,CAAAR,QAAA,CAC/DE,qBAAqB,CACnB,CAAC,EACH,CACN,CAED,cAAe,eAAgBT,MAAM,CAACM,UAAU,CAAE,YAAY,CAAEL,SAAS,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useTheme","baseTheme","jsx","_jsx","jsxs","_jsxs","PageLayout","children","leftSidePanelContent","rightSidePanelContent","theme","composed","className","container","sidePanel","leftSidePanel","join","mainPanel","rightSidePanel"],"sources":["../../../../../src/shared/components/PageLayout/index.tsx"],"sourcesContent":["import type { FunctionComponent, ReactNode } from 'react';\n\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport baseTheme from './base-theme.scss';\n\ntype ThemeKeyT = 'container' | 'leftSidePanel' | 'mainPanel' | 'rightSidePanel'\n | 'sidePanel';\n\ntype PropsT = {\n children?: ReactNode;\n leftSidePanelContent?: ReactNode;\n rightSidePanelContent?: ReactNode;\n theme?: Theme<ThemeKeyT>;\n};\n\n/**\n * Simple and themeable page layout. It keeps the main content centered in\n * a column of limited width, which fills entire viewport on small screens\n * (under `$screen-md = 1024px` size). At larger screens the column keeps\n * `$screen-md` size, and it is centered at the page, surrounded by side\n * panels, where additional content can be displayed.\n *\n * **Children:** Component children are rendered as the content of main panel.\n * @param {object} [props] Component properties.\n * @param {Node} [props.leftSidePanelContent] The content for left side panel.\n * @param {Node} [props.rightSidePanelContent] The content for right side panel.\n * @param {PageLayoutTheme} [props.theme] _Ad hoc_ theme.\n * @param {...any} [props....]\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)\n */\nconst PageLayout: FunctionComponent<PropsT> = ({\n children,\n leftSidePanelContent,\n rightSidePanelContent,\n theme,\n}) => {\n const composed = useTheme('PageLayout', baseTheme, theme);\n return (\n <div className={composed.container}>\n <div className={[composed.sidePanel, composed.leftSidePanel].join(' ')}>\n {leftSidePanelContent}\n </div>\n <div className={composed.mainPanel}>\n {children}\n </div>\n <div className={[composed.sidePanel, composed.rightSidePanel].join(' ')}>\n {rightSidePanelContent}\n </div>\n </div>\n );\n};\n\nexport default PageLayout;\n"],"mappings":"AAEA,OAAqBA,QAAQ,KAAQ,0BAA0B,OAAAC,SAAA,mHAErB,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAY1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACA,KAAM,CAAAC,UAAqC,CAAGA,CAAC,CAC7CC,QAAQ,CACRC,oBAAoB,CACpBC,qBAAqB,CACrBC,KACF,CAAC,GAAK,CACJ,KAAM,CAAAC,QAAQ,CAAGX,QAAQ,CAAC,YAAY,CAAEC,SAAS,CAAES,KAAK,CAAC,CACzD,mBACEL,KAAA,QAAKO,SAAS,CAAED,QAAQ,CAACE,SAAU,CAAAN,QAAA,eACjCJ,IAAA,QAAKS,SAAS,CAAE,CAACD,QAAQ,CAACG,SAAS,CAAEH,QAAQ,CAACI,aAAa,CAAC,CAACC,IAAI,CAAC,GAAG,CAAE,CAAAT,QAAA,CACpEC,oBAAoB,CAClB,CAAC,cACNL,IAAA,QAAKS,SAAS,CAAED,QAAQ,CAACM,SAAU,CAAAV,QAAA,CAChCA,QAAQ,CACN,CAAC,cACNJ,IAAA,QAAKS,SAAS,CAAE,CAACD,QAAQ,CAACG,SAAS,CAAEH,QAAQ,CAACO,cAAc,CAAC,CAACF,IAAI,CAAC,GAAG,CAAE,CAAAT,QAAA,CACrEE,qBAAqB,CACnB,CAAC,EACH,CAET,CAAC,CAED,cAAe,CAAAH,UAAU","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- import{useEffect,useLayoutEffect,useRef,useState}from"react";import themed from"@dr.pogodin/react-themes";const defaultTheme={"context":"tECG8C","ad":"epeH4O","hoc":"_2kFnSt","container":"lV5ZyX","label":"_7qDPW1","textarea":"gkaNJJ","error":"ObwtG4","errorMessage":"ikIw0x","hidden":"-UyujK"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const TextArea=({disabled,error,label,onBlur,onChange,onKeyDown,placeholder,testId,theme,value})=>{const hiddenAreaRef=useRef(null);const[height,setHeight]=useState();const textAreaRef=useRef(null);const[localValue,setLocalValue]=useState(value??"");if(value!==undefined&&localValue!==value)setLocalValue(value);// This resizes text area's height when its width is changed for any reason.
1
+ import{useEffect,useLayoutEffect,useRef,useState}from"react";import{useTheme}from"@dr.pogodin/react-themes";const defaultTheme={"context":"tECG8C","ad":"epeH4O","hoc":"_2kFnSt","container":"lV5ZyX","label":"_7qDPW1","textarea":"gkaNJJ","error":"ObwtG4","errorMessage":"ikIw0x","hidden":"-UyujK"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const TextArea=({disabled,error,label,onBlur,onChange,onKeyDown,placeholder,testId,theme,value})=>{const custom=useTheme("TextArea",defaultTheme,theme);const hiddenAreaRef=useRef(null);const[height,setHeight]=useState();const textAreaRef=useRef(null);const[localValue,setLocalValue]=useState(value??"");if(value!==undefined&&localValue!==value)setLocalValue(value);// This resizes text area's height when its width is changed for any reason.
2
2
  useEffect(()=>{const el=hiddenAreaRef.current;if(!el)return undefined;const cb=()=>{setHeight(el.scrollHeight)};const observer=new ResizeObserver(cb);observer.observe(el);return()=>{observer.disconnect()}},[]);// Resizes the text area when its content is modified.
3
3
  //
4
4
  // NOTE: useLayoutEffect() instead of useEffect() makes difference here,
@@ -6,7 +6,7 @@ useEffect(()=>{const el=hiddenAreaRef.current;if(!el)return undefined;const cb=(
6
6
  // useEffect() it becomes visible how the content is modified first,
7
7
  // and then input height is incremented, if necessary).
8
8
  // See: https://github.com/birdofpreyru/react-utils/issues/313
9
- useLayoutEffect(()=>{const el=hiddenAreaRef.current;if(el)setHeight(el.scrollHeight)},[localValue]);let containerClassName=theme.container;if(error)containerClassName+=` ${theme.error}`;return/*#__PURE__*/_jsxs("div",{className:containerClassName,onFocus:()=>{textAreaRef.current?.focus()},children:[label===undefined?null:/*#__PURE__*/_jsx("div",{className:theme.label,children:label}),/*#__PURE__*/_jsx("textarea",{className:`${theme.textarea} ${theme.hidden}`// This text area is hidden underneath the primary one below,
9
+ useLayoutEffect(()=>{const el=hiddenAreaRef.current;if(el)setHeight(el.scrollHeight)},[localValue]);let containerClassName=custom.container;if(error)containerClassName+=` ${custom.error}`;return/*#__PURE__*/_jsxs("div",{className:containerClassName,onFocus:()=>{textAreaRef.current?.focus()},children:[label===undefined?null:/*#__PURE__*/_jsx("div",{className:custom.label,children:label}),/*#__PURE__*/_jsx("textarea",{className:`${custom.textarea} ${custom.hidden}`// This text area is hidden underneath the primary one below,
10
10
  // and it is used for text measurements, to implement auto-scaling
11
11
  // of the primary textarea's height.
12
12
  ,readOnly:true,ref:hiddenAreaRef// The "-1" value of "tabIndex" removes this hidden text area from
@@ -15,8 +15,8 @@ useLayoutEffect(()=>{const el=hiddenAreaRef.current;if(el)setHeight(el.scrollHei
15
15
  // area is zero, thus collapsing <TextArea> height below the single line
16
16
  // input height. To avoid it we fallback to whitespace (" ") character
17
17
  // here.
18
- ,value:localValue||" "}),/*#__PURE__*/_jsx("textarea",{className:theme.textarea,"data-testid":process.env.NODE_ENV==="production"?undefined:testId,disabled:disabled,onBlur:onBlur// When value is "undefined" the text area is not-managed, and we should
18
+ ,value:localValue||" "}),/*#__PURE__*/_jsx("textarea",{className:custom.textarea,"data-testid":process.env.NODE_ENV==="production"?undefined:testId,disabled:disabled,onBlur:onBlur// When value is "undefined" the text area is not-managed, and we should
19
19
  // manage it internally for the measurement / resizing functionality
20
20
  // to work.
21
- ,onChange:value===undefined?e=>{setLocalValue(e.target.value)}:onChange,onKeyDown:onKeyDown,placeholder:placeholder,ref:textAreaRef,style:{height},value:localValue}),error&&error!==true?/*#__PURE__*/_jsx("div",{className:theme.errorMessage,children:error}):null]})};export default/* #__PURE__ */themed(TextArea,"TextArea",defaultTheme);
21
+ ,onChange:value===undefined?e=>{setLocalValue(e.target.value)}:onChange,onKeyDown:onKeyDown,placeholder:placeholder,ref:textAreaRef,style:{height},value:localValue}),error&&error!==true?/*#__PURE__*/_jsx("div",{className:custom.errorMessage,children:error}):null]})};export default TextArea;
22
22
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useEffect","useLayoutEffect","useRef","useState","themed","defaultTheme","jsx","_jsx","jsxs","_jsxs","TextArea","disabled","error","label","onBlur","onChange","onKeyDown","placeholder","testId","theme","value","hiddenAreaRef","height","setHeight","textAreaRef","localValue","setLocalValue","undefined","el","current","cb","scrollHeight","observer","ResizeObserver","observe","disconnect","containerClassName","container","className","onFocus","focus","children","textarea","hidden","readOnly","ref","tabIndex","process","env","NODE_ENV","e","target","style","errorMessage"],"sources":["../../../../../src/shared/components/TextArea/index.tsx"],"sourcesContent":["import {\n type ChangeEventHandler,\n type FocusEventHandler,\n type FunctionComponent,\n type KeyboardEventHandler,\n type ReactNode,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\n\nimport themed, { type Theme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './style.scss';\n\ntype ThemeKeyT = 'container' | 'error' | 'errorMessage' | 'hidden' | 'label'\n | 'textarea';\n\ntype Props = {\n disabled?: boolean;\n error?: ReactNode;\n label?: string;\n onBlur?: FocusEventHandler<HTMLTextAreaElement>;\n onChange?: ChangeEventHandler<HTMLTextAreaElement>;\n onKeyDown?: KeyboardEventHandler<HTMLTextAreaElement>;\n placeholder?: string;\n testId?: string;\n theme: Theme<ThemeKeyT>;\n value?: string;\n};\n\nconst TextArea: FunctionComponent<Props> = ({\n disabled,\n error,\n label,\n onBlur,\n onChange,\n onKeyDown,\n placeholder,\n testId,\n theme,\n value,\n}) => {\n const hiddenAreaRef = useRef<HTMLTextAreaElement>(null);\n const [height, setHeight] = useState<number | undefined>();\n\n const textAreaRef = useRef<HTMLTextAreaElement>(null);\n\n const [localValue, setLocalValue] = useState(value ?? '');\n if (value !== undefined && localValue !== value) setLocalValue(value);\n\n // This resizes text area's height when its width is changed for any reason.\n useEffect(() => {\n const el = hiddenAreaRef.current;\n if (!el) return undefined;\n\n const cb = () => {\n setHeight(el.scrollHeight);\n };\n const observer = new ResizeObserver(cb);\n observer.observe(el);\n\n return () => {\n observer.disconnect();\n };\n }, []);\n\n // Resizes the text area when its content is modified.\n //\n // NOTE: useLayoutEffect() instead of useEffect() makes difference here,\n // as it helps to avoid visible \"content/height\" jumps (i.e. with just\n // useEffect() it becomes visible how the content is modified first,\n // and then input height is incremented, if necessary).\n // See: https://github.com/birdofpreyru/react-utils/issues/313\n useLayoutEffect(() => {\n const el = hiddenAreaRef.current;\n if (el) setHeight(el.scrollHeight);\n }, [localValue]);\n\n let containerClassName = theme.container;\n if (error) containerClassName += ` ${theme.error}`;\n\n return (\n <div\n className={containerClassName}\n onFocus={() => {\n textAreaRef.current?.focus();\n }}\n >\n {label === undefined ? null : <div className={theme.label}>{label}</div>}\n <textarea\n className={`${theme.textarea} ${theme.hidden}`}\n\n // This text area is hidden underneath the primary one below,\n // and it is used for text measurements, to implement auto-scaling\n // of the primary textarea's height.\n readOnly\n ref={hiddenAreaRef}\n\n // The \"-1\" value of \"tabIndex\" removes this hidden text area from\n // the tab-focus-chain.\n tabIndex={-1}\n\n // NOTE: With empty string value (\"\") the scrolling height of this text\n // area is zero, thus collapsing <TextArea> height below the single line\n // input height. To avoid it we fallback to whitespace (\" \") character\n // here.\n value={localValue || ' '}\n />\n <textarea\n className={theme.textarea}\n data-testid={process.env.NODE_ENV === 'production' ? undefined : testId}\n disabled={disabled}\n onBlur={onBlur}\n\n // When value is \"undefined\" the text area is not-managed, and we should\n // manage it internally for the measurement / resizing functionality\n // to work.\n onChange={\n value === undefined\n ? (e) => {\n setLocalValue(e.target.value);\n } : onChange\n }\n onKeyDown={onKeyDown}\n placeholder={placeholder}\n ref={textAreaRef}\n style={{ height }}\n value={localValue}\n />\n {error && error !== true\n ? <div className={theme.errorMessage}>{error}</div>\n : null}\n </div>\n );\n};\n\nexport default /* #__PURE__ */ themed(TextArea, 'TextArea', defaultTheme);\n"],"mappings":"AAAA,OAMEA,SAAS,CACTC,eAAe,CACfC,MAAM,CACNC,QAAQ,KACH,OAAO,CAEd,MAAO,CAAAC,MAAM,KAAsB,0BAA0B,OAAAC,YAAA,0KAErB,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAkBxC,KAAM,CAAAC,QAAkC,CAAGA,CAAC,CAC1CC,QAAQ,CACRC,KAAK,CACLC,KAAK,CACLC,MAAM,CACNC,QAAQ,CACRC,SAAS,CACTC,WAAW,CACXC,MAAM,CACNC,KAAK,CACLC,KACF,CAAC,GAAK,CACJ,KAAM,CAAAC,aAAa,CAAGnB,MAAM,CAAsB,IAAI,CAAC,CACvD,KAAM,CAACoB,MAAM,CAAEC,SAAS,CAAC,CAAGpB,QAAQ,CAAqB,CAAC,CAE1D,KAAM,CAAAqB,WAAW,CAAGtB,MAAM,CAAsB,IAAI,CAAC,CAErD,KAAM,CAACuB,UAAU,CAAEC,aAAa,CAAC,CAAGvB,QAAQ,CAACiB,KAAK,EAAI,EAAE,CAAC,CACzD,GAAIA,KAAK,GAAKO,SAAS,EAAIF,UAAU,GAAKL,KAAK,CAAEM,aAAa,CAACN,KAAK,CAAC,CAErE;AACApB,SAAS,CAAC,IAAM,CACd,KAAM,CAAA4B,EAAE,CAAGP,aAAa,CAACQ,OAAO,CAChC,GAAI,CAACD,EAAE,CAAE,MAAO,CAAAD,SAAS,CAEzB,KAAM,CAAAG,EAAE,CAAGA,CAAA,GAAM,CACfP,SAAS,CAACK,EAAE,CAACG,YAAY,CAC3B,CAAC,CACD,KAAM,CAAAC,QAAQ,CAAG,GAAI,CAAAC,cAAc,CAACH,EAAE,CAAC,CACvCE,QAAQ,CAACE,OAAO,CAACN,EAAE,CAAC,CAEpB,MAAO,IAAM,CACXI,QAAQ,CAACG,UAAU,CAAC,CACtB,CACF,CAAC,CAAE,EAAE,CAAC,CAEN;AACA;AACA;AACA;AACA;AACA;AACA;AACAlC,eAAe,CAAC,IAAM,CACpB,KAAM,CAAA2B,EAAE,CAAGP,aAAa,CAACQ,OAAO,CAChC,GAAID,EAAE,CAAEL,SAAS,CAACK,EAAE,CAACG,YAAY,CACnC,CAAC,CAAE,CAACN,UAAU,CAAC,CAAC,CAEhB,GAAI,CAAAW,kBAAkB,CAAGjB,KAAK,CAACkB,SAAS,CACxC,GAAIzB,KAAK,CAAEwB,kBAAkB,EAAI,IAAIjB,KAAK,CAACP,KAAK,EAAE,CAElD,mBACEH,KAAA,QACE6B,SAAS,CAAEF,kBAAmB,CAC9BG,OAAO,CAAEA,CAAA,GAAM,CACbf,WAAW,CAACK,OAAO,EAAEW,KAAK,CAAC,CAC7B,CAAE,CAAAC,QAAA,EAED5B,KAAK,GAAKc,SAAS,CAAG,IAAI,cAAGpB,IAAA,QAAK+B,SAAS,CAAEnB,KAAK,CAACN,KAAM,CAAA4B,QAAA,CAAE5B,KAAK,CAAM,CAAC,cACxEN,IAAA,aACE+B,SAAS,CAAE,GAAGnB,KAAK,CAACuB,QAAQ,IAAIvB,KAAK,CAACwB,MAAM,EAE5C;AACA;AACA;AAAA,CACAC,QAAQ,MACRC,GAAG,CAAExB,aAEL;AACA;AAAA,CACAyB,QAAQ,CAAE,CAAC,CAEX;AACA;AACA;AACA;AAAA,CACA1B,KAAK,CAAEK,UAAU,EAAI,GAAI,CAC1B,CAAC,cACFlB,IAAA,aACE+B,SAAS,CAAEnB,KAAK,CAACuB,QAAS,CAC1B,cAAaK,OAAO,CAACC,GAAG,CAACC,QAAQ,GAAK,YAAY,CAAGtB,SAAS,CAAGT,MAAO,CACxEP,QAAQ,CAAEA,QAAS,CACnBG,MAAM,CAAEA,MAER;AACA;AACA;AAAA,CACAC,QAAQ,CACNK,KAAK,GAAKO,SAAS,CACduB,CAAC,EAAK,CACPxB,aAAa,CAACwB,CAAC,CAACC,MAAM,CAAC/B,KAAK,CAC9B,CAAC,CAAGL,QACP,CACDC,SAAS,CAAEA,SAAU,CACrBC,WAAW,CAAEA,WAAY,CACzB4B,GAAG,CAAErB,WAAY,CACjB4B,KAAK,CAAE,CAAE9B,MAAO,CAAE,CAClBF,KAAK,CAAEK,UAAW,CACnB,CAAC,CACDb,KAAK,EAAIA,KAAK,GAAK,IAAI,cACpBL,IAAA,QAAK+B,SAAS,CAAEnB,KAAK,CAACkC,YAAa,CAAAZ,QAAA,CAAE7B,KAAK,CAAM,CAAC,CACjD,IAAI,EACL,CAET,CAAC,CAED,cAAe,eAAgBR,MAAM,CAACM,QAAQ,CAAE,UAAU,CAAEL,YAAY,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useEffect","useLayoutEffect","useRef","useState","useTheme","defaultTheme","jsx","_jsx","jsxs","_jsxs","TextArea","disabled","error","label","onBlur","onChange","onKeyDown","placeholder","testId","theme","value","custom","hiddenAreaRef","height","setHeight","textAreaRef","localValue","setLocalValue","undefined","el","current","cb","scrollHeight","observer","ResizeObserver","observe","disconnect","containerClassName","container","className","onFocus","focus","children","textarea","hidden","readOnly","ref","tabIndex","process","env","NODE_ENV","e","target","style","errorMessage"],"sources":["../../../../../src/shared/components/TextArea/index.tsx"],"sourcesContent":["import {\n type ChangeEventHandler,\n type FocusEventHandler,\n type FunctionComponent,\n type KeyboardEventHandler,\n type ReactNode,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\n\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './style.scss';\n\ntype ThemeKeyT = 'container' | 'error' | 'errorMessage' | 'hidden' | 'label'\n | 'textarea';\n\ntype Props = {\n disabled?: boolean;\n error?: ReactNode;\n label?: string;\n onBlur?: FocusEventHandler<HTMLTextAreaElement>;\n onChange?: ChangeEventHandler<HTMLTextAreaElement>;\n onKeyDown?: KeyboardEventHandler<HTMLTextAreaElement>;\n placeholder?: string;\n testId?: string;\n theme?: Theme<ThemeKeyT>;\n value?: string;\n};\n\nconst TextArea: FunctionComponent<Props> = ({\n disabled,\n error,\n label,\n onBlur,\n onChange,\n onKeyDown,\n placeholder,\n testId,\n theme,\n value,\n}) => {\n const custom = useTheme('TextArea', defaultTheme, theme);\n\n const hiddenAreaRef = useRef<HTMLTextAreaElement>(null);\n const [height, setHeight] = useState<number | undefined>();\n\n const textAreaRef = useRef<HTMLTextAreaElement>(null);\n\n const [localValue, setLocalValue] = useState(value ?? '');\n if (value !== undefined && localValue !== value) setLocalValue(value);\n\n // This resizes text area's height when its width is changed for any reason.\n useEffect(() => {\n const el = hiddenAreaRef.current;\n if (!el) return undefined;\n\n const cb = () => {\n setHeight(el.scrollHeight);\n };\n const observer = new ResizeObserver(cb);\n observer.observe(el);\n\n return () => {\n observer.disconnect();\n };\n }, []);\n\n // Resizes the text area when its content is modified.\n //\n // NOTE: useLayoutEffect() instead of useEffect() makes difference here,\n // as it helps to avoid visible \"content/height\" jumps (i.e. with just\n // useEffect() it becomes visible how the content is modified first,\n // and then input height is incremented, if necessary).\n // See: https://github.com/birdofpreyru/react-utils/issues/313\n useLayoutEffect(() => {\n const el = hiddenAreaRef.current;\n if (el) setHeight(el.scrollHeight);\n }, [localValue]);\n\n let containerClassName = custom.container;\n if (error) containerClassName += ` ${custom.error}`;\n\n return (\n <div\n className={containerClassName}\n onFocus={() => {\n textAreaRef.current?.focus();\n }}\n >\n {label === undefined ? null : <div className={custom.label}>{label}</div>}\n <textarea\n className={`${custom.textarea} ${custom.hidden}`}\n\n // This text area is hidden underneath the primary one below,\n // and it is used for text measurements, to implement auto-scaling\n // of the primary textarea's height.\n readOnly\n ref={hiddenAreaRef}\n\n // The \"-1\" value of \"tabIndex\" removes this hidden text area from\n // the tab-focus-chain.\n tabIndex={-1}\n\n // NOTE: With empty string value (\"\") the scrolling height of this text\n // area is zero, thus collapsing <TextArea> height below the single line\n // input height. To avoid it we fallback to whitespace (\" \") character\n // here.\n value={localValue || ' '}\n />\n <textarea\n className={custom.textarea}\n data-testid={process.env.NODE_ENV === 'production' ? undefined : testId}\n disabled={disabled}\n onBlur={onBlur}\n\n // When value is \"undefined\" the text area is not-managed, and we should\n // manage it internally for the measurement / resizing functionality\n // to work.\n onChange={\n value === undefined\n ? (e) => {\n setLocalValue(e.target.value);\n } : onChange\n }\n onKeyDown={onKeyDown}\n placeholder={placeholder}\n ref={textAreaRef}\n style={{ height }}\n value={localValue}\n />\n {error && error !== true\n ? <div className={custom.errorMessage}>{error}</div>\n : null}\n </div>\n );\n};\n\nexport default TextArea;\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- import themed from"@dr.pogodin/react-themes";const defaultTheme={"context":"eVCJf-","ad":"CU2B6H","hoc":"_1V5iVx","bouncing":"h6ZYmQ","container":"VDVI-X","circle":"Y2rzbL"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";/**
1
+ import{useTheme}from"@dr.pogodin/react-themes";const defaultTheme={"context":"eVCJf-","ad":"CU2B6H","hoc":"_1V5iVx","bouncing":"h6ZYmQ","container":"VDVI-X","circle":"Y2rzbL"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";/**
2
2
  * Throbber is an "action in progress" indicator, which renders
3
3
  * three bouncing circles as a simple pending activity indicator,
4
4
  * and can be further themed to a certain degree.
@@ -6,5 +6,5 @@ import themed from"@dr.pogodin/react-themes";const defaultTheme={"context":"eVCJ
6
6
  * @param {ThrobberTheme} [props.theme] _Ad hoc_ theme.
7
7
  * @param {...any} [props....]
8
8
  * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)
9
- */const Throbber=({theme})=>/*#__PURE__*/_jsxs("span",{className:theme.container,children:[/*#__PURE__*/_jsx("span",{className:theme.circle}),/*#__PURE__*/_jsx("span",{className:theme.circle}),/*#__PURE__*/_jsx("span",{className:theme.circle})]});export default/* #__PURE__ */themed(Throbber,"Throbber",defaultTheme);
9
+ */const Throbber=({theme})=>{const custom=useTheme("Throbber",defaultTheme,theme);return/*#__PURE__*/_jsxs("span",{className:custom.container,children:[/*#__PURE__*/_jsx("span",{className:custom.circle}),/*#__PURE__*/_jsx("span",{className:custom.circle}),/*#__PURE__*/_jsx("span",{className:custom.circle})]})};export default Throbber;
10
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["themed","defaultTheme","jsx","_jsx","jsxs","_jsxs","Throbber","theme","className","container","children","circle"],"sources":["../../../../../src/shared/components/Throbber/index.tsx"],"sourcesContent":["import themed, { type Theme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './theme.scss';\n\ntype ThemeKeyT = 'bouncing' | 'circle' | 'container';\n\ntype PropsT = {\n theme: Theme<ThemeKeyT>;\n};\n\n/**\n * Throbber is an \"action in progress\" indicator, which renders\n * three bouncing circles as a simple pending activity indicator,\n * and can be further themed to a certain degree.\n * @param {object} [props] Component properties.\n * @param {ThrobberTheme} [props.theme] _Ad hoc_ theme.\n * @param {...any} [props....]\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)\n */\nconst Throbber: React.FunctionComponent<PropsT> = ({ theme }) => (\n <span className={theme.container}>\n <span className={theme.circle} />\n <span className={theme.circle} />\n <span className={theme.circle} />\n </span>\n);\n\nexport default /* #__PURE__ */ themed(Throbber, 'Throbber', defaultTheme);\n"],"mappings":"AAAA,MAAO,CAAAA,MAAM,KAAsB,0BAA0B,OAAAC,YAAA,+GAErB,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAQxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACA,KAAM,CAAAC,QAAyC,CAAGA,CAAC,CAAEC,KAAM,CAAC,gBAC1DF,KAAA,SAAMG,SAAS,CAAED,KAAK,CAACE,SAAU,CAAAC,QAAA,eAC/BP,IAAA,SAAMK,SAAS,CAAED,KAAK,CAACI,MAAO,CAAE,CAAC,cACjCR,IAAA,SAAMK,SAAS,CAAED,KAAK,CAACI,MAAO,CAAE,CAAC,cACjCR,IAAA,SAAMK,SAAS,CAAED,KAAK,CAACI,MAAO,CAAE,CAAC,EAC7B,CACP,CAED,cAAe,eAAgBX,MAAM,CAACM,QAAQ,CAAE,UAAU,CAAEL,YAAY,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useTheme","defaultTheme","jsx","_jsx","jsxs","_jsxs","Throbber","theme","custom","className","container","children","circle"],"sources":["../../../../../src/shared/components/Throbber/index.tsx"],"sourcesContent":["import type { FunctionComponent } from 'react';\n\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './theme.scss';\n\ntype ThemeKeyT = 'bouncing' | 'circle' | 'container';\n\ntype PropsT = {\n theme?: Theme<ThemeKeyT>;\n};\n\n/**\n * Throbber is an \"action in progress\" indicator, which renders\n * three bouncing circles as a simple pending activity indicator,\n * and can be further themed to a certain degree.\n * @param {object} [props] Component properties.\n * @param {ThrobberTheme} [props.theme] _Ad hoc_ theme.\n * @param {...any} [props....]\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)\n */\nconst Throbber: FunctionComponent<PropsT> = ({ theme }) => {\n const custom = useTheme('Throbber', defaultTheme, theme);\n\n return (\n <span className={custom.container}>\n <span className={custom.circle} />\n <span className={custom.circle} />\n <span className={custom.circle} />\n </span>\n );\n};\n\nexport default Throbber;\n"],"mappings":"AAEA,OAAqBA,QAAQ,KAAQ,0BAA0B,OAAAC,YAAA,+GAEvB,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAQxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACA,KAAM,CAAAC,QAAmC,CAAGA,CAAC,CAAEC,KAAM,CAAC,GAAK,CACzD,KAAM,CAAAC,MAAM,CAAGR,QAAQ,CAAC,UAAU,CAAEC,YAAY,CAAEM,KAAK,CAAC,CAExD,mBACEF,KAAA,SAAMI,SAAS,CAAED,MAAM,CAACE,SAAU,CAAAC,QAAA,eAChCR,IAAA,SAAMM,SAAS,CAAED,MAAM,CAACI,MAAO,CAAE,CAAC,cAClCT,IAAA,SAAMM,SAAS,CAAED,MAAM,CAACI,MAAO,CAAE,CAAC,cAClCT,IAAA,SAAMM,SAAS,CAAED,MAAM,CAACI,MAAO,CAAE,CAAC,EAC9B,CAEV,CAAC,CAED,cAAe,CAAAN,QAAQ","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- /* global window */import{useEffect,useRef,useState}from"react";import themed from"@dr.pogodin/react-themes";import Tooltip,{PLACEMENTS}from"./Tooltip.js";const defaultTheme={"ad":"n6OiU9","hoc":"zwsjGc","context":"JVJPcU","appearance":"_9U4YiR","arrow":"_9n65k-","container":"uA1tHZ","wrapper":"JFVmGf"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";/**
1
+ /* global window */import{useEffect,useRef,useState}from"react";import{useTheme}from"@dr.pogodin/react-themes";import Tooltip,{PLACEMENTS}from"./Tooltip.js";const defaultTheme={"ad":"n6OiU9","hoc":"zwsjGc","context":"JVJPcU","appearance":"_9U4YiR","arrow":"_9n65k-","container":"uA1tHZ","wrapper":"JFVmGf"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";/**
2
2
  * Implements a simple to use and themeable tooltip component, _e.g._
3
3
  * ```js
4
4
  * <WithTooltip tip="This is example tooltip.">
@@ -11,7 +11,7 @@
11
11
  * @param tip &ndash; Anything React is able to render,
12
12
  * _e.g._ a tooltip text. This will be the tooltip content.
13
13
  * @param {WithTooltipTheme} props.theme _Ad hoc_ theme.
14
- */const Wrapper=({children,placement=PLACEMENTS.ABOVE_CURSOR,tip,theme})=>{const{current:heap}=useRef({lastCursorX:0,lastCursorY:0,timerId:undefined,triggeredByTouch:false});const tooltipRef=useRef(null);const wrapperRef=useRef(null);const[showTooltip,setShowTooltip]=useState(false);const updatePortalPosition=(cursorX,cursorY)=>{if(showTooltip){const wrapperRect=wrapperRef.current.getBoundingClientRect();if(cursorX<wrapperRect.left||cursorX>wrapperRect.right||cursorY<wrapperRect.top||cursorY>wrapperRect.bottom){setShowTooltip(false)}else if(tooltipRef.current){tooltipRef.current.pointTo(cursorX+window.scrollX,cursorY+window.scrollY,placement,wrapperRef.current)}}else{heap.lastCursorX=cursorX;heap.lastCursorY=cursorY;// If tooltip was triggered by a touch, we delay its opening by a bit,
14
+ */const WithTooltip=({children,placement=PLACEMENTS.ABOVE_CURSOR,tip,theme})=>{const custom=useTheme("WithTooltip",defaultTheme,theme);const{current:heap}=useRef({lastCursorX:0,lastCursorY:0,timerId:undefined,triggeredByTouch:false});const tooltipRef=useRef(null);const wrapperRef=useRef(null);const[showTooltip,setShowTooltip]=useState(false);const updatePortalPosition=(cursorX,cursorY)=>{if(showTooltip){const wrapperRect=wrapperRef.current.getBoundingClientRect();if(cursorX<wrapperRect.left||cursorX>wrapperRect.right||cursorY<wrapperRect.top||cursorY>wrapperRect.bottom){setShowTooltip(false)}else if(tooltipRef.current){tooltipRef.current.pointTo(cursorX+window.scrollX,cursorY+window.scrollY,placement,wrapperRef.current)}}else{heap.lastCursorX=cursorX;heap.lastCursorY=cursorY;// If tooltip was triggered by a touch, we delay its opening by a bit,
15
15
  // to ensure it was not a touch-click - in the case of touch click we
16
16
  // want to do the click, rather than show the tooltip, and the delay
17
17
  // gives click handler a chance to abort the tooltip openning.
@@ -21,5 +21,5 @@ if(heap.triggeredByTouch){heap.timerId??=setTimeout(()=>{heap.triggeredByTouch=f
21
21
  // once opened (because similar call above does not have effect until
22
22
  // the tooltip is fully mounted, and that is delayed to future rendering
23
23
  // cycle due to the implementation).
24
- if(tooltipRef.current){tooltipRef.current.pointTo(heap.lastCursorX+window.scrollX,heap.lastCursorY+window.scrollY,placement,wrapperRef.current)}const listener=()=>{setShowTooltip(false)};window.addEventListener("scroll",listener);return()=>{window.removeEventListener("scroll",listener)}}return undefined},[heap.lastCursorX,heap.lastCursorY,placement,showTooltip,tip]);return/*#__PURE__*/_jsxs("div",{className:theme.wrapper,onClick:()=>{if(heap.timerId){clearTimeout(heap.timerId);heap.timerId=undefined;heap.triggeredByTouch=false}},onMouseLeave:()=>{setShowTooltip(false)},onMouseMove:e=>{updatePortalPosition(e.clientX,e.clientY)},onTouchStart:()=>{heap.triggeredByTouch=true},ref:wrapperRef,role:"presentation",children:[showTooltip&&tip!==null?/*#__PURE__*/_jsx(Tooltip,{ref:tooltipRef,theme:theme,children:tip}):null,children]})};const ThemedWrapper=/* #__PURE__ */themed(Wrapper,"WithTooltip",defaultTheme);const e=ThemedWrapper;e.PLACEMENTS=PLACEMENTS;export default e;
24
+ if(tooltipRef.current){tooltipRef.current.pointTo(heap.lastCursorX+window.scrollX,heap.lastCursorY+window.scrollY,placement,wrapperRef.current)}const listener=()=>{setShowTooltip(false)};window.addEventListener("scroll",listener);return()=>{window.removeEventListener("scroll",listener)}}return undefined},[heap.lastCursorX,heap.lastCursorY,placement,showTooltip,tip]);return/*#__PURE__*/_jsxs("div",{className:custom.wrapper,onClick:()=>{if(heap.timerId){clearTimeout(heap.timerId);heap.timerId=undefined;heap.triggeredByTouch=false}},onMouseLeave:()=>{setShowTooltip(false)},onMouseMove:e=>{updatePortalPosition(e.clientX,e.clientY)},onTouchStart:()=>{heap.triggeredByTouch=true},ref:wrapperRef,role:"presentation",children:[showTooltip&&tip!==null?/*#__PURE__*/_jsx(Tooltip,{ref:tooltipRef,theme:custom,children:tip}):null,children]})};const e=WithTooltip;e.PLACEMENTS=PLACEMENTS;export default e;
25
25
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useEffect","useRef","useState","themed","Tooltip","PLACEMENTS","defaultTheme","jsx","_jsx","jsxs","_jsxs","Wrapper","children","placement","ABOVE_CURSOR","tip","theme","current","heap","lastCursorX","lastCursorY","timerId","undefined","triggeredByTouch","tooltipRef","wrapperRef","showTooltip","setShowTooltip","updatePortalPosition","cursorX","cursorY","wrapperRect","getBoundingClientRect","left","right","top","bottom","pointTo","window","scrollX","scrollY","setTimeout","listener","addEventListener","removeEventListener","className","wrapper","onClick","clearTimeout","onMouseLeave","onMouseMove","e","clientX","clientY","onTouchStart","ref","role","ThemedWrapper"],"sources":["../../../../../src/shared/components/WithTooltip/index.tsx"],"sourcesContent":["/* global window */\n\nimport {\n type FunctionComponent,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport themed, { type Theme } from '@dr.pogodin/react-themes';\n\nimport Tooltip, {\n type ThemeKeysT as TooltipThemeKeysT,\n PLACEMENTS,\n} from './Tooltip';\n\nimport defaultTheme from './default-theme.scss';\n\ntype PropsT = {\n children?: ReactNode;\n placement?: PLACEMENTS;\n tip?: ReactNode;\n theme: Theme<'wrapper' | TooltipThemeKeysT>;\n};\n\ntype TooltipRefT = {\n pointTo: (\n x: number,\n y: number,\n placement: PLACEMENTS,\n wrapperRef: HTMLDivElement,\n ) => void;\n};\n\ntype HeapT = {\n lastCursorX: number;\n lastCursorY: number;\n triggeredByTouch: boolean;\n timerId?: NodeJS.Timeout;\n};\n\n/**\n * Implements a simple to use and themeable tooltip component, _e.g._\n * ```js\n * <WithTooltip tip=\"This is example tooltip.\">\n * <p>Hover to see the tooltip.</p>\n * </WithTooltip>\n * ```\n * **Children:** Children are rendered in the place of `<WithTooltip>`,\n * and when hovered the tooltip is shown. By default the wrapper itself is\n * `<div>` block with `display: inline-block`.\n * @param tip &ndash; Anything React is able to render,\n * _e.g._ a tooltip text. This will be the tooltip content.\n * @param {WithTooltipTheme} props.theme _Ad hoc_ theme.\n */\nconst Wrapper: FunctionComponent<PropsT> = ({\n children,\n placement = PLACEMENTS.ABOVE_CURSOR,\n tip,\n theme,\n}) => {\n const { current: heap } = useRef<HeapT>({\n lastCursorX: 0,\n lastCursorY: 0,\n timerId: undefined,\n triggeredByTouch: false,\n });\n const tooltipRef = useRef<TooltipRefT>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const [showTooltip, setShowTooltip] = useState(false);\n\n const updatePortalPosition = (cursorX: number, cursorY: number) => {\n if (showTooltip) {\n const wrapperRect = wrapperRef.current!.getBoundingClientRect();\n if (\n cursorX < wrapperRect.left\n || cursorX > wrapperRect.right\n || cursorY < wrapperRect.top\n || cursorY > wrapperRect.bottom\n ) {\n setShowTooltip(false);\n } else if (tooltipRef.current) {\n tooltipRef.current.pointTo(\n cursorX + window.scrollX,\n cursorY + window.scrollY,\n placement,\n wrapperRef.current!,\n );\n }\n } else {\n heap.lastCursorX = cursorX;\n heap.lastCursorY = cursorY;\n\n // If tooltip was triggered by a touch, we delay its opening by a bit,\n // to ensure it was not a touch-click - in the case of touch click we\n // want to do the click, rather than show the tooltip, and the delay\n // gives click handler a chance to abort the tooltip openning.\n if (heap.triggeredByTouch) {\n heap.timerId ??= setTimeout(() => {\n heap.triggeredByTouch = false;\n heap.timerId = undefined;\n setShowTooltip(true);\n }, 300);\n\n // Otherwise we can just open the tooltip right away.\n } else setShowTooltip(true);\n }\n };\n\n useEffect(() => {\n if (showTooltip && tip !== null) {\n // This is necessary to ensure that even when a single mouse event\n // arrives to a tool-tipped component, the tooltip is correctly positioned\n // once opened (because similar call above does not have effect until\n // the tooltip is fully mounted, and that is delayed to future rendering\n // cycle due to the implementation).\n if (tooltipRef.current) {\n tooltipRef.current.pointTo(\n heap.lastCursorX + window.scrollX,\n heap.lastCursorY + window.scrollY,\n placement,\n wrapperRef.current!,\n );\n }\n\n const listener = () => {\n setShowTooltip(false);\n };\n window.addEventListener('scroll', listener);\n return () => {\n window.removeEventListener('scroll', listener);\n };\n }\n return undefined;\n }, [\n heap.lastCursorX,\n heap.lastCursorY,\n placement,\n showTooltip,\n tip,\n ]);\n\n return (\n <div\n className={theme.wrapper}\n onClick={() => {\n if (heap.timerId) {\n clearTimeout(heap.timerId);\n heap.timerId = undefined;\n heap.triggeredByTouch = false;\n }\n }}\n onMouseLeave={() => {\n setShowTooltip(false);\n }}\n onMouseMove={(e) => {\n updatePortalPosition(e.clientX, e.clientY);\n }}\n onTouchStart={() => {\n heap.triggeredByTouch = true;\n }}\n ref={wrapperRef}\n role=\"presentation\"\n >\n {\n showTooltip && tip !== null\n ? <Tooltip ref={tooltipRef} theme={theme}>{tip}</Tooltip>\n : null\n }\n {children}\n </div>\n );\n};\n\nconst ThemedWrapper = /* #__PURE__ */ themed(Wrapper, 'WithTooltip', defaultTheme);\n\ntype ExportT = typeof ThemedWrapper & {\n PLACEMENTS: typeof PLACEMENTS;\n};\n\nconst e: ExportT = ThemedWrapper as ExportT;\n\ne.PLACEMENTS = PLACEMENTS;\n\nexport default e;\n"],"mappings":"AAAA,mBAEA,OAGEA,SAAS,CACTC,MAAM,CACNC,QAAQ,KACH,OAAO,CAEd,MAAO,CAAAC,MAAM,KAAsB,0BAA0B,OAEtD,CAAAC,OAAO,EAEZC,UAAU,0BAAAC,YAAA,oIAGoC,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAyBhD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACA,KAAM,CAAAC,OAAkC,CAAGA,CAAC,CAC1CC,QAAQ,CACRC,SAAS,CAAGR,UAAU,CAACS,YAAY,CACnCC,GAAG,CACHC,KACF,CAAC,GAAK,CACJ,KAAM,CAAEC,OAAO,CAAEC,IAAK,CAAC,CAAGjB,MAAM,CAAQ,CACtCkB,WAAW,CAAE,CAAC,CACdC,WAAW,CAAE,CAAC,CACdC,OAAO,CAAEC,SAAS,CAClBC,gBAAgB,CAAE,KACpB,CAAC,CAAC,CACF,KAAM,CAAAC,UAAU,CAAGvB,MAAM,CAAc,IAAI,CAAC,CAC5C,KAAM,CAAAwB,UAAU,CAAGxB,MAAM,CAAiB,IAAI,CAAC,CAC/C,KAAM,CAACyB,WAAW,CAAEC,cAAc,CAAC,CAAGzB,QAAQ,CAAC,KAAK,CAAC,CAErD,KAAM,CAAA0B,oBAAoB,CAAGA,CAACC,OAAe,CAAEC,OAAe,GAAK,CACjE,GAAIJ,WAAW,CAAE,CACf,KAAM,CAAAK,WAAW,CAAGN,UAAU,CAACR,OAAO,CAAEe,qBAAqB,CAAC,CAAC,CAC/D,GACEH,OAAO,CAAGE,WAAW,CAACE,IAAI,EACvBJ,OAAO,CAAGE,WAAW,CAACG,KAAK,EAC3BJ,OAAO,CAAGC,WAAW,CAACI,GAAG,EACzBL,OAAO,CAAGC,WAAW,CAACK,MAAM,CAC/B,CACAT,cAAc,CAAC,KAAK,CACtB,CAAC,IAAM,IAAIH,UAAU,CAACP,OAAO,CAAE,CAC7BO,UAAU,CAACP,OAAO,CAACoB,OAAO,CACxBR,OAAO,CAAGS,MAAM,CAACC,OAAO,CACxBT,OAAO,CAAGQ,MAAM,CAACE,OAAO,CACxB3B,SAAS,CACTY,UAAU,CAACR,OACb,CACF,CACF,CAAC,IAAM,CACLC,IAAI,CAACC,WAAW,CAAGU,OAAO,CAC1BX,IAAI,CAACE,WAAW,CAAGU,OAAO,CAE1B;AACA;AACA;AACA;AACA,GAAIZ,IAAI,CAACK,gBAAgB,CAAE,CACzBL,IAAI,CAACG,OAAO,GAAKoB,UAAU,CAAC,IAAM,CAChCvB,IAAI,CAACK,gBAAgB,CAAG,KAAK,CAC7BL,IAAI,CAACG,OAAO,CAAGC,SAAS,CACxBK,cAAc,CAAC,IAAI,CACrB,CAAC,CAAE,GAAG,CAAC,CAET;AACA,CAAC,IAAM,CAAAA,cAAc,CAAC,IAAI,CAC5B,CACF,CAAC,CAED3B,SAAS,CAAC,IAAM,CACd,GAAI0B,WAAW,EAAIX,GAAG,GAAK,IAAI,CAAE,CAC/B;AACA;AACA;AACA;AACA;AACA,GAAIS,UAAU,CAACP,OAAO,CAAE,CACtBO,UAAU,CAACP,OAAO,CAACoB,OAAO,CACxBnB,IAAI,CAACC,WAAW,CAAGmB,MAAM,CAACC,OAAO,CACjCrB,IAAI,CAACE,WAAW,CAAGkB,MAAM,CAACE,OAAO,CACjC3B,SAAS,CACTY,UAAU,CAACR,OACb,CACF,CAEA,KAAM,CAAAyB,QAAQ,CAAGA,CAAA,GAAM,CACrBf,cAAc,CAAC,KAAK,CACtB,CAAC,CACDW,MAAM,CAACK,gBAAgB,CAAC,QAAQ,CAAED,QAAQ,CAAC,CAC3C,MAAO,IAAM,CACXJ,MAAM,CAACM,mBAAmB,CAAC,QAAQ,CAAEF,QAAQ,CAC/C,CACF,CACA,MAAO,CAAApB,SACT,CAAC,CAAE,CACDJ,IAAI,CAACC,WAAW,CAChBD,IAAI,CAACE,WAAW,CAChBP,SAAS,CACTa,WAAW,CACXX,GAAG,CACJ,CAAC,CAEF,mBACEL,KAAA,QACEmC,SAAS,CAAE7B,KAAK,CAAC8B,OAAQ,CACzBC,OAAO,CAAEA,CAAA,GAAM,CACb,GAAI7B,IAAI,CAACG,OAAO,CAAE,CAChB2B,YAAY,CAAC9B,IAAI,CAACG,OAAO,CAAC,CAC1BH,IAAI,CAACG,OAAO,CAAGC,SAAS,CACxBJ,IAAI,CAACK,gBAAgB,CAAG,KAC1B,CACF,CAAE,CACF0B,YAAY,CAAEA,CAAA,GAAM,CAClBtB,cAAc,CAAC,KAAK,CACtB,CAAE,CACFuB,WAAW,CAAGC,CAAC,EAAK,CAClBvB,oBAAoB,CAACuB,CAAC,CAACC,OAAO,CAAED,CAAC,CAACE,OAAO,CAC3C,CAAE,CACFC,YAAY,CAAEA,CAAA,GAAM,CAClBpC,IAAI,CAACK,gBAAgB,CAAG,IAC1B,CAAE,CACFgC,GAAG,CAAE9B,UAAW,CAChB+B,IAAI,CAAC,cAAc,CAAA5C,QAAA,EAGjBc,WAAW,EAAIX,GAAG,GAAK,IAAI,cACvBP,IAAA,CAACJ,OAAO,EAACmD,GAAG,CAAE/B,UAAW,CAACR,KAAK,CAAEA,KAAM,CAAAJ,QAAA,CAAEG,GAAG,CAAU,CAAC,CACvD,IAAI,CAETH,QAAQ,EACN,CAET,CAAC,CAED,KAAM,CAAA6C,aAAa,CAAG,eAAgBtD,MAAM,CAACQ,OAAO,CAAE,aAAa,CAAEL,YAAY,CAAC,CAMlF,KAAM,CAAA6C,CAAU,CAAGM,aAAwB,CAE3CN,CAAC,CAAC9C,UAAU,CAAGA,UAAU,CAEzB,cAAe,CAAA8C,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useEffect","useRef","useState","useTheme","Tooltip","PLACEMENTS","defaultTheme","jsx","_jsx","jsxs","_jsxs","WithTooltip","children","placement","ABOVE_CURSOR","tip","theme","custom","current","heap","lastCursorX","lastCursorY","timerId","undefined","triggeredByTouch","tooltipRef","wrapperRef","showTooltip","setShowTooltip","updatePortalPosition","cursorX","cursorY","wrapperRect","getBoundingClientRect","left","right","top","bottom","pointTo","window","scrollX","scrollY","setTimeout","listener","addEventListener","removeEventListener","className","wrapper","onClick","clearTimeout","onMouseLeave","onMouseMove","e","clientX","clientY","onTouchStart","ref","role"],"sources":["../../../../../src/shared/components/WithTooltip/index.tsx"],"sourcesContent":["/* global window */\n\nimport {\n type FunctionComponent,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport Tooltip, {\n type ThemeKeysT as TooltipThemeKeysT,\n PLACEMENTS,\n} from './Tooltip';\n\nimport defaultTheme from './default-theme.scss';\n\ntype PropsT = {\n children?: ReactNode;\n placement?: PLACEMENTS;\n tip?: ReactNode;\n theme?: Theme<'wrapper' | TooltipThemeKeysT>;\n};\n\ntype TooltipRefT = {\n pointTo: (\n x: number,\n y: number,\n placement: PLACEMENTS,\n wrapperRef: HTMLDivElement,\n ) => void;\n};\n\ntype HeapT = {\n lastCursorX: number;\n lastCursorY: number;\n triggeredByTouch: boolean;\n timerId?: NodeJS.Timeout;\n};\n\n/**\n * Implements a simple to use and themeable tooltip component, _e.g._\n * ```js\n * <WithTooltip tip=\"This is example tooltip.\">\n * <p>Hover to see the tooltip.</p>\n * </WithTooltip>\n * ```\n * **Children:** Children are rendered in the place of `<WithTooltip>`,\n * and when hovered the tooltip is shown. By default the wrapper itself is\n * `<div>` block with `display: inline-block`.\n * @param tip &ndash; Anything React is able to render,\n * _e.g._ a tooltip text. This will be the tooltip content.\n * @param {WithTooltipTheme} props.theme _Ad hoc_ theme.\n */\nconst WithTooltip: FunctionComponent<PropsT> = ({\n children,\n placement = PLACEMENTS.ABOVE_CURSOR,\n tip,\n theme,\n}) => {\n const custom = useTheme('WithTooltip', defaultTheme, theme);\n\n const { current: heap } = useRef<HeapT>({\n lastCursorX: 0,\n lastCursorY: 0,\n timerId: undefined,\n triggeredByTouch: false,\n });\n const tooltipRef = useRef<TooltipRefT>(null);\n const wrapperRef = useRef<HTMLDivElement>(null);\n const [showTooltip, setShowTooltip] = useState(false);\n\n const updatePortalPosition = (cursorX: number, cursorY: number) => {\n if (showTooltip) {\n const wrapperRect = wrapperRef.current!.getBoundingClientRect();\n if (\n cursorX < wrapperRect.left\n || cursorX > wrapperRect.right\n || cursorY < wrapperRect.top\n || cursorY > wrapperRect.bottom\n ) {\n setShowTooltip(false);\n } else if (tooltipRef.current) {\n tooltipRef.current.pointTo(\n cursorX + window.scrollX,\n cursorY + window.scrollY,\n placement,\n wrapperRef.current!,\n );\n }\n } else {\n heap.lastCursorX = cursorX;\n heap.lastCursorY = cursorY;\n\n // If tooltip was triggered by a touch, we delay its opening by a bit,\n // to ensure it was not a touch-click - in the case of touch click we\n // want to do the click, rather than show the tooltip, and the delay\n // gives click handler a chance to abort the tooltip openning.\n if (heap.triggeredByTouch) {\n heap.timerId ??= setTimeout(() => {\n heap.triggeredByTouch = false;\n heap.timerId = undefined;\n setShowTooltip(true);\n }, 300);\n\n // Otherwise we can just open the tooltip right away.\n } else setShowTooltip(true);\n }\n };\n\n useEffect(() => {\n if (showTooltip && tip !== null) {\n // This is necessary to ensure that even when a single mouse event\n // arrives to a tool-tipped component, the tooltip is correctly positioned\n // once opened (because similar call above does not have effect until\n // the tooltip is fully mounted, and that is delayed to future rendering\n // cycle due to the implementation).\n if (tooltipRef.current) {\n tooltipRef.current.pointTo(\n heap.lastCursorX + window.scrollX,\n heap.lastCursorY + window.scrollY,\n placement,\n wrapperRef.current!,\n );\n }\n\n const listener = () => {\n setShowTooltip(false);\n };\n window.addEventListener('scroll', listener);\n return () => {\n window.removeEventListener('scroll', listener);\n };\n }\n return undefined;\n }, [\n heap.lastCursorX,\n heap.lastCursorY,\n placement,\n showTooltip,\n tip,\n ]);\n\n return (\n <div\n className={custom.wrapper}\n onClick={() => {\n if (heap.timerId) {\n clearTimeout(heap.timerId);\n heap.timerId = undefined;\n heap.triggeredByTouch = false;\n }\n }}\n onMouseLeave={() => {\n setShowTooltip(false);\n }}\n onMouseMove={(e) => {\n updatePortalPosition(e.clientX, e.clientY);\n }}\n onTouchStart={() => {\n heap.triggeredByTouch = true;\n }}\n ref={wrapperRef}\n role=\"presentation\"\n >\n {\n showTooltip && tip !== null\n ? <Tooltip ref={tooltipRef} theme={custom}>{tip}</Tooltip>\n : null\n }\n {children}\n </div>\n );\n};\n\ntype ExportT = typeof WithTooltip & {\n PLACEMENTS: typeof PLACEMENTS;\n};\n\nconst e: ExportT = WithTooltip as ExportT;\n\ne.PLACEMENTS = PLACEMENTS;\n\nexport default e;\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- import qs from"qs";import themed from"@dr.pogodin/react-themes";import Throbber from"../Throbber/index.js";const baseTheme={"context":"Pa7GiX","ad":"NikZ57","hoc":"FydyFQ","container":"pQTzJV","video":"iFTALT"};const throbberTheme={"context":"_0Piy3R","ad":"GD-lgk","hoc":"T5TGzT","container":"IgN6Uf"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";/**
1
+ import qs from"qs";import{useTheme}from"@dr.pogodin/react-themes";import Throbber from"../Throbber/index.js";const defaultTheme={"context":"Pa7GiX","ad":"NikZ57","hoc":"FydyFQ","container":"pQTzJV","video":"iFTALT"};const throbberTheme={"context":"_0Piy3R","ad":"GD-lgk","hoc":"T5TGzT","container":"IgN6Uf"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";/**
2
2
  * A component for embeding a YouTube video.
3
3
  * @param [props] Component properties.
4
4
  * @param [props.autoplay] If `true` the video will start to play
@@ -12,8 +12,8 @@ import qs from"qs";import themed from"@dr.pogodin/react-themes";import Throbber
12
12
  * @param [props.theme] _Ad hoc_ theme.
13
13
  * @param [props.title] The `title` attribute to add to the player
14
14
  * IFrame.
15
- */const YouTubeVideo=({autoplay,src,theme,title})=>{const srcParts=src.split("?");let[url]=srcParts;const[,queryString]=srcParts;const query=queryString?qs.parse(queryString):{};const videoId=query.v??url?.match(/\/([a-zA-Z0-9-_]*)$/)?.[1];url=`https://www.youtube.com/embed/${videoId}`;delete query.v;query.autoplay=autoplay?"1":"0";url+=`?${qs.stringify(query)}`;// TODO: https://developers.google.com/youtube/player_parameters
15
+ */const YouTubeVideo=({autoplay,src,theme,title})=>{const custom=useTheme("YouTubeVideo",defaultTheme,theme);const srcParts=src.split("?");let[url]=srcParts;const[,queryString]=srcParts;const query=queryString?qs.parse(queryString):{};const videoId=query.v??url?.match(/\/([a-zA-Z0-9-_]*)$/)?.[1];url=`https://www.youtube.com/embed/${videoId}`;delete query.v;query.autoplay=autoplay?"1":"0";url+=`?${qs.stringify(query)}`;// TODO: https://developers.google.com/youtube/player_parameters
16
16
  // More query parameters can be exposed via the component props.
17
- return/*#__PURE__*/_jsxs("div",{className:theme.container,children:[/*#__PURE__*/_jsx(Throbber,{theme:throbberTheme}),/*#__PURE__*/_jsx("iframe",{// eslint-disable-line react/iframe-missing-sandbox
18
- allow:"autoplay",allowFullScreen:true,className:theme.video,src:url,title:title})]})};export default/* #__PURE__ */themed(YouTubeVideo,"YouTubeVideo",baseTheme);
17
+ return/*#__PURE__*/_jsxs("div",{className:custom.container,children:[/*#__PURE__*/_jsx(Throbber,{theme:throbberTheme}),/*#__PURE__*/_jsx("iframe",{// eslint-disable-line react/iframe-missing-sandbox
18
+ allow:"autoplay",allowFullScreen:true,className:custom.video,src:url,title:title})]})};export default YouTubeVideo;
19
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["qs","themed","Throbber","baseTheme","throbberTheme","jsx","_jsx","jsxs","_jsxs","YouTubeVideo","autoplay","src","theme","title","srcParts","split","url","queryString","query","parse","videoId","v","match","stringify","className","container","children","allow","allowFullScreen","video"],"sources":["../../../../../src/shared/components/YouTubeVideo/index.tsx"],"sourcesContent":["import qs from 'qs';\n\nimport themed, { type Theme } from '@dr.pogodin/react-themes';\n\nimport Throbber from 'components/Throbber';\n\nimport baseTheme from './base.scss';\nimport throbberTheme from './throbber.scss';\n\ntype ComponentThemeT = Theme<'container' | 'video'>;\n\ntype PropsT = {\n autoplay?: boolean;\n src: string;\n theme: ComponentThemeT;\n title?: string;\n};\n\n/**\n * A component for embeding a YouTube video.\n * @param [props] Component properties.\n * @param [props.autoplay] If `true` the video will start to play\n * automatically once loaded.\n * @param [props.src] URL of the video to play. Can be in any of\n * the following formats, and keeps any additional query parameters understood\n * by the YouTube IFrame player:\n * - `https://www.youtube.com/watch?v=NdF6Rmt6Ado`\n * - `https://youtu.be/NdF6Rmt6Ado`\n * - `https://www.youtube.com/embed/NdF6Rmt6Ado`\n * @param [props.theme] _Ad hoc_ theme.\n * @param [props.title] The `title` attribute to add to the player\n * IFrame.\n */\nconst YouTubeVideo: React.FunctionComponent<PropsT> = ({\n autoplay,\n src,\n theme,\n title,\n}) => {\n const srcParts = src.split('?');\n let [url] = srcParts;\n const [, queryString] = srcParts;\n const query = queryString ? qs.parse(queryString) : {};\n\n const videoId = query.v ?? url?.match(/\\/([a-zA-Z0-9-_]*)$/)?.[1];\n url = `https://www.youtube.com/embed/${videoId as string}`;\n\n delete query.v;\n query.autoplay = autoplay ? '1' : '0';\n url += `?${qs.stringify(query)}`;\n\n // TODO: https://developers.google.com/youtube/player_parameters\n // More query parameters can be exposed via the component props.\n\n return (\n <div className={theme.container}>\n <Throbber theme={throbberTheme} />\n {/* TODO: I guess, we better add the sanbox, but right now I don't have\n time to carefully explore which restrictions should be lifted to allow\n embed YouTube player to work... sometime later we'll take care of it */\n }\n <iframe // eslint-disable-line react/iframe-missing-sandbox\n allow=\"autoplay\"\n allowFullScreen\n className={theme.video}\n src={url}\n title={title}\n />\n </div>\n );\n};\n\nexport default /* #__PURE__ */ themed(YouTubeVideo, 'YouTubeVideo', baseTheme);\n"],"mappings":"AAAA,MAAO,CAAAA,EAAE,KAAM,IAAI,CAEnB,MAAO,CAAAC,MAAM,KAAsB,0BAA0B,OAEtD,CAAAC,QAAQ,kCAAAC,SAAA,+FAAAC,aAAA,yEAG6B,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAW5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACA,KAAM,CAAAC,YAA6C,CAAGA,CAAC,CACrDC,QAAQ,CACRC,GAAG,CACHC,KAAK,CACLC,KACF,CAAC,GAAK,CACJ,KAAM,CAAAC,QAAQ,CAAGH,GAAG,CAACI,KAAK,CAAC,GAAG,CAAC,CAC/B,GAAI,CAACC,GAAG,CAAC,CAAGF,QAAQ,CACpB,KAAM,EAAGG,WAAW,CAAC,CAAGH,QAAQ,CAChC,KAAM,CAAAI,KAAK,CAAGD,WAAW,CAAGjB,EAAE,CAACmB,KAAK,CAACF,WAAW,CAAC,CAAG,CAAC,CAAC,CAEtD,KAAM,CAAAG,OAAO,CAAGF,KAAK,CAACG,CAAC,EAAIL,GAAG,EAAEM,KAAK,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CACjEN,GAAG,CAAG,iCAAiCI,OAAO,EAAY,CAE1D,MAAO,CAAAF,KAAK,CAACG,CAAC,CACdH,KAAK,CAACR,QAAQ,CAAGA,QAAQ,CAAG,GAAG,CAAG,GAAG,CACrCM,GAAG,EAAI,IAAIhB,EAAE,CAACuB,SAAS,CAACL,KAAK,CAAC,EAAE,CAEhC;AACA;AAEA,mBACEV,KAAA,QAAKgB,SAAS,CAAEZ,KAAK,CAACa,SAAU,CAAAC,QAAA,eAC9BpB,IAAA,CAACJ,QAAQ,EAACU,KAAK,CAAER,aAAc,CAAE,CAAC,cAKlCE,IAAA,WAAQ;AACNqB,KAAK,CAAC,UAAU,CAChBC,eAAe,MACfJ,SAAS,CAAEZ,KAAK,CAACiB,KAAM,CACvBlB,GAAG,CAAEK,GAAI,CACTH,KAAK,CAAEA,KAAM,CACd,CAAC,EACC,CAET,CAAC,CAED,cAAe,eAAgBZ,MAAM,CAACQ,YAAY,CAAE,cAAc,CAAEN,SAAS,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["qs","useTheme","Throbber","defaultTheme","throbberTheme","jsx","_jsx","jsxs","_jsxs","YouTubeVideo","autoplay","src","theme","title","custom","srcParts","split","url","queryString","query","parse","videoId","v","match","stringify","className","container","children","allow","allowFullScreen","video"],"sources":["../../../../../src/shared/components/YouTubeVideo/index.tsx"],"sourcesContent":["import qs from 'qs';\nimport type { FunctionComponent } from 'react';\n\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport Throbber from 'components/Throbber';\n\nimport defaultTheme from './base.scss';\nimport throbberTheme from './throbber.scss';\n\ntype ThemeT = Theme<'container' | 'video'>;\n\ntype PropsT = {\n autoplay?: boolean;\n src: string;\n theme?: ThemeT;\n title?: string;\n};\n\n/**\n * A component for embeding a YouTube video.\n * @param [props] Component properties.\n * @param [props.autoplay] If `true` the video will start to play\n * automatically once loaded.\n * @param [props.src] URL of the video to play. Can be in any of\n * the following formats, and keeps any additional query parameters understood\n * by the YouTube IFrame player:\n * - `https://www.youtube.com/watch?v=NdF6Rmt6Ado`\n * - `https://youtu.be/NdF6Rmt6Ado`\n * - `https://www.youtube.com/embed/NdF6Rmt6Ado`\n * @param [props.theme] _Ad hoc_ theme.\n * @param [props.title] The `title` attribute to add to the player\n * IFrame.\n */\nconst YouTubeVideo: FunctionComponent<PropsT> = ({\n autoplay,\n src,\n theme,\n title,\n}) => {\n const custom = useTheme('YouTubeVideo', defaultTheme, theme);\n\n const srcParts = src.split('?');\n let [url] = srcParts;\n const [, queryString] = srcParts;\n const query = queryString ? qs.parse(queryString) : {};\n\n const videoId = query.v ?? url?.match(/\\/([a-zA-Z0-9-_]*)$/)?.[1];\n url = `https://www.youtube.com/embed/${videoId as string}`;\n\n delete query.v;\n query.autoplay = autoplay ? '1' : '0';\n url += `?${qs.stringify(query)}`;\n\n // TODO: https://developers.google.com/youtube/player_parameters\n // More query parameters can be exposed via the component props.\n\n return (\n <div className={custom.container}>\n <Throbber theme={throbberTheme} />\n {/* TODO: I guess, we better add the sanbox, but right now I don't have\n time to carefully explore which restrictions should be lifted to allow\n embed YouTube player to work... sometime later we'll take care of it */\n }\n <iframe // eslint-disable-line react/iframe-missing-sandbox\n allow=\"autoplay\"\n allowFullScreen\n className={custom.video}\n src={url}\n title={title}\n />\n </div>\n );\n};\n\nexport default YouTubeVideo;\n"],"mappings":"AAAA,MAAO,CAAAA,EAAE,KAAM,IAAI,CAGnB,OAAqBC,QAAQ,KAAQ,0BAA0B,OAExD,CAAAC,QAAQ,kCAAAC,YAAA,+FAAAC,aAAA,yEAG6B,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAW5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GACA,KAAM,CAAAC,YAAuC,CAAGA,CAAC,CAC/CC,QAAQ,CACRC,GAAG,CACHC,KAAK,CACLC,KACF,CAAC,GAAK,CACJ,KAAM,CAAAC,MAAM,CAAGb,QAAQ,CAAC,cAAc,CAAEE,YAAY,CAAES,KAAK,CAAC,CAE5D,KAAM,CAAAG,QAAQ,CAAGJ,GAAG,CAACK,KAAK,CAAC,GAAG,CAAC,CAC/B,GAAI,CAACC,GAAG,CAAC,CAAGF,QAAQ,CACpB,KAAM,EAAGG,WAAW,CAAC,CAAGH,QAAQ,CAChC,KAAM,CAAAI,KAAK,CAAGD,WAAW,CAAGlB,EAAE,CAACoB,KAAK,CAACF,WAAW,CAAC,CAAG,CAAC,CAAC,CAEtD,KAAM,CAAAG,OAAO,CAAGF,KAAK,CAACG,CAAC,EAAIL,GAAG,EAAEM,KAAK,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CACjEN,GAAG,CAAG,iCAAiCI,OAAO,EAAY,CAE1D,MAAO,CAAAF,KAAK,CAACG,CAAC,CACdH,KAAK,CAACT,QAAQ,CAAGA,QAAQ,CAAG,GAAG,CAAG,GAAG,CACrCO,GAAG,EAAI,IAAIjB,EAAE,CAACwB,SAAS,CAACL,KAAK,CAAC,EAAE,CAEhC;AACA;AAEA,mBACEX,KAAA,QAAKiB,SAAS,CAAEX,MAAM,CAACY,SAAU,CAAAC,QAAA,eAC/BrB,IAAA,CAACJ,QAAQ,EAACU,KAAK,CAAER,aAAc,CAAE,CAAC,cAKlCE,IAAA,WAAQ;AACNsB,KAAK,CAAC,UAAU,CAChBC,eAAe,MACfJ,SAAS,CAAEX,MAAM,CAACgB,KAAM,CACxBnB,GAAG,CAAEM,GAAI,CACTJ,KAAK,CAAEA,KAAM,CACd,CAAC,EACC,CAET,CAAC,CAED,cAAe,CAAAJ,YAAY","ignoreList":[]}
@@ -1,8 +1,8 @@
1
- import"core-js/modules/es.iterator.filter.js";import"core-js/modules/es.iterator.constructor.js";import"core-js/modules/es.iterator.filter.js";import{useEffect,useRef,useState}from"react";import themed from"@dr.pogodin/react-themes";import{optionValueName}from"../common.js";import Options,{areEqual}from"./Options/index.js";const defaultTheme={"context":"SNj3wp","ad":"T6eOJ-","hoc":"KG-OKN","container":"SzHHPE","label":"KTG4ai","dropdown":"xdotm7","option":"y-WCDM","select":"PP5Siy","arrow":"_7-A7Lh","active":"RoOAZK","upward":"_--5Xpy"};import{Fragment as _Fragment,jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const BaseCustomDropdown=({filter,label,onChange,options,theme,value})=>{const[active,setActive]=useState(false);const dropdownRef=useRef(null);const opsRef=useRef(null);const[opsPos,setOpsPos]=useState();const[upward,setUpward]=useState(false);useEffect(()=>{if(!active)return undefined;let id;const cb=()=>{const anchor=dropdownRef.current?.getBoundingClientRect();const opsRect=opsRef.current?.measure();if(anchor&&opsRect){const fitsDown=anchor.bottom+opsRect.height<(window.visualViewport?.height??0);const fitsUp=anchor.top-opsRect.height>0;const up=!fitsDown&&fitsUp;setUpward(up);const pos=up?{left:anchor.left,top:anchor.top-opsRect.height-1,width:anchor.width}:{left:anchor.left,top:anchor.bottom,width:anchor.width};setOpsPos(now=>areEqual(now,pos)?now:pos)}id=requestAnimationFrame(cb)};requestAnimationFrame(cb);return()=>{cancelAnimationFrame(id)}},[active]);const openList=e=>{const view=window.visualViewport;const rect=dropdownRef.current.getBoundingClientRect();setActive(true);// NOTE: This first opens the dropdown off-screen, where it is measured
1
+ import"core-js/modules/es.iterator.filter.js";import"core-js/modules/es.iterator.constructor.js";import"core-js/modules/es.iterator.filter.js";import{useEffect,useRef,useState}from"react";import{useTheme}from"@dr.pogodin/react-themes";import{optionValueName}from"../common.js";import Options,{areEqual}from"./Options/index.js";const defaultTheme={"context":"SNj3wp","ad":"T6eOJ-","hoc":"KG-OKN","container":"SzHHPE","label":"KTG4ai","dropdown":"xdotm7","option":"y-WCDM","select":"PP5Siy","arrow":"_7-A7Lh","active":"RoOAZK","upward":"_--5Xpy"};import{Fragment as _Fragment,jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const CustomDropdown=({filter,label,onChange,options,theme,value})=>{const custom=useTheme("CustomDropdown",defaultTheme,theme);const[active,setActive]=useState(false);const dropdownRef=useRef(null);const opsRef=useRef(null);const[opsPos,setOpsPos]=useState();const[upward,setUpward]=useState(false);useEffect(()=>{if(!active)return undefined;let id;const cb=()=>{const anchor=dropdownRef.current?.getBoundingClientRect();const opsRect=opsRef.current?.measure();if(anchor&&opsRect){const fitsDown=anchor.bottom+opsRect.height<(window.visualViewport?.height??0);const fitsUp=anchor.top-opsRect.height>0;const up=!fitsDown&&fitsUp;setUpward(up);const pos=up?{left:anchor.left,top:anchor.top-opsRect.height-1,width:anchor.width}:{left:anchor.left,top:anchor.bottom,width:anchor.width};setOpsPos(now=>areEqual(now,pos)?now:pos)}id=requestAnimationFrame(cb)};requestAnimationFrame(cb);return()=>{cancelAnimationFrame(id)}},[active]);const openList=e=>{const view=window.visualViewport;const rect=dropdownRef.current.getBoundingClientRect();setActive(true);// NOTE: This first opens the dropdown off-screen, where it is measured
2
2
  // by an effect declared above, and then positioned below, or above
3
3
  // the original dropdown element, depending where it fits best
4
4
  // (if we first open it downward, it would flick if we immediately
5
5
  // move it above, at least with the current position update via local
6
6
  // react state, and not imperatively).
7
- setOpsPos({left:view?.width??0,top:view?.height??0,width:rect.width});e.stopPropagation()};let selected=/*#__PURE__*/_jsx(_Fragment,{children:"\u200C"});for(const option of options){if(!filter||filter(option)){const[iValue,iName]=optionValueName(option);if(iValue===value){selected=iName;break}}}let containerClassName=theme.container;if(active)containerClassName+=` ${theme.active}`;let opsContainerClass=theme.select??"";if(upward){containerClassName+=` ${theme.upward}`;opsContainerClass+=` ${theme.upward}`}return/*#__PURE__*/_jsxs("div",{className:containerClassName,children:[label===undefined?null:/*#__PURE__*/_jsx("div",{className:theme.label,children:label}),/*#__PURE__*/_jsxs("div",{className:theme.dropdown,onClick:openList,onKeyDown:e=>{if(e.key==="Enter")openList(e)},ref:dropdownRef,role:"listbox",tabIndex:0,children:[selected,/*#__PURE__*/_jsx("div",{className:theme.arrow})]}),active?/*#__PURE__*/_jsx(Options,{containerClass:opsContainerClass,containerStyle:opsPos,onCancel:()=>{setActive(false)},onChange:newValue=>{setActive(false);if(onChange)onChange(newValue)},optionClass:theme.option??"",options:options,ref:opsRef}):null]})};export default/* #__PURE__ */themed(BaseCustomDropdown,"CustomDropdown",defaultTheme);
7
+ setOpsPos({left:view?.width??0,top:view?.height??0,width:rect.width});e.stopPropagation()};let selected=/*#__PURE__*/_jsx(_Fragment,{children:"\u200C"});for(const option of options){if(!filter||filter(option)){const[iValue,iName]=optionValueName(option);if(iValue===value){selected=iName;break}}}let containerClassName=custom.container;if(active)containerClassName+=` ${custom.active}`;let opsContainerClass=custom.select??"";if(upward){containerClassName+=` ${custom.upward}`;opsContainerClass+=` ${custom.upward}`}return/*#__PURE__*/_jsxs("div",{className:containerClassName,children:[label===undefined?null:/*#__PURE__*/_jsx("div",{className:custom.label,children:label}),/*#__PURE__*/_jsxs("div",{className:custom.dropdown,onClick:openList,onKeyDown:e=>{if(e.key==="Enter")openList(e)},ref:dropdownRef,role:"listbox",tabIndex:0,children:[selected,/*#__PURE__*/_jsx("div",{className:custom.arrow})]}),active?/*#__PURE__*/_jsx(Options,{containerClass:opsContainerClass,containerStyle:opsPos,onCancel:()=>{setActive(false)},onChange:newValue=>{setActive(false);if(onChange)onChange(newValue)},optionClass:custom.option??"",options:options,ref:opsRef}):null]})};export default CustomDropdown;
8
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["useEffect","useRef","useState","themed","optionValueName","Options","areEqual","defaultTheme","Fragment","_Fragment","jsx","_jsx","jsxs","_jsxs","BaseCustomDropdown","filter","label","onChange","options","theme","value","active","setActive","dropdownRef","opsRef","opsPos","setOpsPos","upward","setUpward","undefined","id","cb","anchor","current","getBoundingClientRect","opsRect","measure","fitsDown","bottom","height","window","visualViewport","fitsUp","top","up","pos","left","width","now","requestAnimationFrame","cancelAnimationFrame","openList","e","view","rect","stopPropagation","selected","children","option","iValue","iName","containerClassName","container","opsContainerClass","select","className","dropdown","onClick","onKeyDown","key","ref","role","tabIndex","arrow","containerClass","containerStyle","onCancel","newValue","optionClass"],"sources":["../../../../../../src/shared/components/selectors/CustomDropdown/index.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\nimport themed from '@dr.pogodin/react-themes';\n\nimport { type PropsT, type ValueT, optionValueName } from '../common';\n\nimport Options, { type ContainerPosT, type RefT, areEqual } from './Options';\n\nimport defaultTheme from './theme.scss';\n\nconst BaseCustomDropdown: React.FunctionComponent<\n PropsT<React.ReactNode, (value: ValueT) => void>\n> = ({\n filter,\n label,\n onChange,\n options,\n theme,\n value,\n}) => {\n const [active, setActive] = useState(false);\n\n const dropdownRef = useRef<HTMLDivElement>(null);\n const opsRef = useRef<RefT>(null);\n\n const [opsPos, setOpsPos] = useState<ContainerPosT>();\n const [upward, setUpward] = useState(false);\n\n useEffect(() => {\n if (!active) return undefined;\n\n let id: number;\n const cb = () => {\n const anchor = dropdownRef.current?.getBoundingClientRect();\n const opsRect = opsRef.current?.measure();\n if (anchor && opsRect) {\n const fitsDown = anchor.bottom + opsRect.height\n < (window.visualViewport?.height ?? 0);\n const fitsUp = anchor.top - opsRect.height > 0;\n\n const up = !fitsDown && fitsUp;\n setUpward(up);\n\n const pos = up ? {\n left: anchor.left,\n top: anchor.top - opsRect.height - 1,\n width: anchor.width,\n } : {\n left: anchor.left,\n top: anchor.bottom,\n width: anchor.width,\n };\n\n setOpsPos((now) => (areEqual(now, pos) ? now : pos));\n }\n id = requestAnimationFrame(cb);\n };\n requestAnimationFrame(cb);\n\n return () => {\n cancelAnimationFrame(id);\n };\n }, [active]);\n\n const openList = (\n e: React.KeyboardEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>,\n ) => {\n const view = window.visualViewport;\n const rect = dropdownRef.current!.getBoundingClientRect();\n setActive(true);\n\n // NOTE: This first opens the dropdown off-screen, where it is measured\n // by an effect declared above, and then positioned below, or above\n // the original dropdown element, depending where it fits best\n // (if we first open it downward, it would flick if we immediately\n // move it above, at least with the current position update via local\n // react state, and not imperatively).\n setOpsPos({\n left: view?.width ?? 0,\n top: view?.height ?? 0,\n width: rect.width,\n });\n\n e.stopPropagation();\n };\n\n let selected: React.ReactNode = <>&zwnj;</>;\n for (const option of options) {\n if (!filter || filter(option)) {\n const [iValue, iName] = optionValueName(option);\n if (iValue === value) {\n selected = iName;\n break;\n }\n }\n }\n\n let containerClassName = theme.container;\n if (active) containerClassName += ` ${theme.active}`;\n\n let opsContainerClass = theme.select ?? '';\n if (upward) {\n containerClassName += ` ${theme.upward}`;\n opsContainerClass += ` ${theme.upward}`;\n }\n\n return (\n <div className={containerClassName}>\n {label === undefined ? null\n : <div className={theme.label}>{label}</div>}\n <div\n className={theme.dropdown}\n onClick={openList}\n onKeyDown={(e) => {\n if (e.key === 'Enter') openList(e);\n }}\n ref={dropdownRef}\n role=\"listbox\"\n tabIndex={0}\n >\n {selected}\n <div className={theme.arrow} />\n </div>\n {\n active ? (\n <Options\n containerClass={opsContainerClass}\n containerStyle={opsPos}\n onCancel={() => {\n setActive(false);\n }}\n onChange={(newValue) => {\n setActive(false);\n if (onChange) onChange(newValue);\n }}\n optionClass={theme.option ?? ''}\n options={options}\n ref={opsRef}\n />\n ) : null\n }\n </div>\n );\n};\n\nexport default /* #__PURE__ */ themed(BaseCustomDropdown, 'CustomDropdown', defaultTheme);\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useEffect","useRef","useState","useTheme","optionValueName","Options","areEqual","defaultTheme","Fragment","_Fragment","jsx","_jsx","jsxs","_jsxs","CustomDropdown","filter","label","onChange","options","theme","value","custom","active","setActive","dropdownRef","opsRef","opsPos","setOpsPos","upward","setUpward","undefined","id","cb","anchor","current","getBoundingClientRect","opsRect","measure","fitsDown","bottom","height","window","visualViewport","fitsUp","top","up","pos","left","width","now","requestAnimationFrame","cancelAnimationFrame","openList","e","view","rect","stopPropagation","selected","children","option","iValue","iName","containerClassName","container","opsContainerClass","select","className","dropdown","onClick","onKeyDown","key","ref","role","tabIndex","arrow","containerClass","containerStyle","onCancel","newValue","optionClass"],"sources":["../../../../../../src/shared/components/selectors/CustomDropdown/index.tsx"],"sourcesContent":["import {\n type FunctionComponent,\n type ReactNode,\n useEffect,\n useRef,\n useState,\n} from 'react';\n\nimport { useTheme } from '@dr.pogodin/react-themes';\n\nimport { type PropsT, type ValueT, optionValueName } from '../common';\n\nimport Options, { type ContainerPosT, type RefT, areEqual } from './Options';\n\nimport defaultTheme from './theme.scss';\n\nconst CustomDropdown: FunctionComponent<\n PropsT<ReactNode, (value: ValueT) => void>\n> = ({\n filter,\n label,\n onChange,\n options,\n theme,\n value,\n}) => {\n const custom = useTheme('CustomDropdown', defaultTheme, theme);\n\n const [active, setActive] = useState(false);\n\n const dropdownRef = useRef<HTMLDivElement>(null);\n const opsRef = useRef<RefT>(null);\n\n const [opsPos, setOpsPos] = useState<ContainerPosT>();\n const [upward, setUpward] = useState(false);\n\n useEffect(() => {\n if (!active) return undefined;\n\n let id: number;\n const cb = () => {\n const anchor = dropdownRef.current?.getBoundingClientRect();\n const opsRect = opsRef.current?.measure();\n if (anchor && opsRect) {\n const fitsDown = anchor.bottom + opsRect.height\n < (window.visualViewport?.height ?? 0);\n const fitsUp = anchor.top - opsRect.height > 0;\n\n const up = !fitsDown && fitsUp;\n setUpward(up);\n\n const pos = up ? {\n left: anchor.left,\n top: anchor.top - opsRect.height - 1,\n width: anchor.width,\n } : {\n left: anchor.left,\n top: anchor.bottom,\n width: anchor.width,\n };\n\n setOpsPos((now) => (areEqual(now, pos) ? now : pos));\n }\n id = requestAnimationFrame(cb);\n };\n requestAnimationFrame(cb);\n\n return () => {\n cancelAnimationFrame(id);\n };\n }, [active]);\n\n const openList = (\n e: React.KeyboardEvent<HTMLDivElement> | React.MouseEvent<HTMLDivElement>,\n ) => {\n const view = window.visualViewport;\n const rect = dropdownRef.current!.getBoundingClientRect();\n setActive(true);\n\n // NOTE: This first opens the dropdown off-screen, where it is measured\n // by an effect declared above, and then positioned below, or above\n // the original dropdown element, depending where it fits best\n // (if we first open it downward, it would flick if we immediately\n // move it above, at least with the current position update via local\n // react state, and not imperatively).\n setOpsPos({\n left: view?.width ?? 0,\n top: view?.height ?? 0,\n width: rect.width,\n });\n\n e.stopPropagation();\n };\n\n let selected: React.ReactNode = <>&zwnj;</>;\n for (const option of options) {\n if (!filter || filter(option)) {\n const [iValue, iName] = optionValueName(option);\n if (iValue === value) {\n selected = iName;\n break;\n }\n }\n }\n\n let containerClassName = custom.container;\n if (active) containerClassName += ` ${custom.active}`;\n\n let opsContainerClass = custom.select ?? '';\n if (upward) {\n containerClassName += ` ${custom.upward}`;\n opsContainerClass += ` ${custom.upward}`;\n }\n\n return (\n <div className={containerClassName}>\n {label === undefined ? null\n : <div className={custom.label}>{label}</div>}\n <div\n className={custom.dropdown}\n onClick={openList}\n onKeyDown={(e) => {\n if (e.key === 'Enter') openList(e);\n }}\n ref={dropdownRef}\n role=\"listbox\"\n tabIndex={0}\n >\n {selected}\n <div className={custom.arrow} />\n </div>\n {\n active ? (\n <Options\n containerClass={opsContainerClass}\n containerStyle={opsPos}\n onCancel={() => {\n setActive(false);\n }}\n onChange={(newValue) => {\n setActive(false);\n if (onChange) onChange(newValue);\n }}\n optionClass={custom.option ?? ''}\n options={options}\n ref={opsRef}\n />\n ) : null\n }\n </div>\n );\n};\n\nexport default CustomDropdown;\n"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,5 @@
1
1
  import"core-js/modules/es.iterator.filter.js";import"core-js/modules/es.array.push.js";import"core-js/modules/es.iterator.constructor.js";import"core-js/modules/es.iterator.filter.js";// Implements dropdown based on the native HTML <select> element.
2
- import themed from"@dr.pogodin/react-themes";import{optionValueName}from"../common.js";const defaultTheme={"context":"WbwY1Y","ad":"AP5hsY","hoc":"ODAJeW","dropdown":"wabw76","arrow":"WFSB9z","container":"vE9M8Z","active":"sfLSJA","label":"bQLBhS","option":"wgCtdC","hiddenOption":"ty19C2","select":"ntbzPR","invalid":"_3CzMM4"};/**
2
+ import{useTheme}from"@dr.pogodin/react-themes";import{optionValueName}from"../common.js";const defaultTheme={"context":"WbwY1Y","ad":"AP5hsY","hoc":"ODAJeW","dropdown":"wabw76","arrow":"WFSB9z","container":"vE9M8Z","active":"sfLSJA","label":"bQLBhS","option":"wgCtdC","hiddenOption":"ty19C2","select":"ntbzPR","invalid":"_3CzMM4"};/**
3
3
  * Implements a themeable dropdown list. Internally it is rendered with help of
4
4
  * the standard HTML `<select>` element, thus the styling support is somewhat
5
5
  * limited.
@@ -17,9 +17,9 @@ import themed from"@dr.pogodin/react-themes";import{optionValueName}from"../comm
17
17
  * @param [props.value] Currently selected value.
18
18
  * @param [props....]
19
19
  * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)
20
- */import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const Dropdown=({filter,label,onChange,options,testId,theme,value})=>{let isValidValue=false;const optionElements=[];for(const option of options){if(!filter||filter(option)){const[iValue,iName]=optionValueName(option);isValidValue||=iValue===value;optionElements.push(/*#__PURE__*/_jsx("option",{className:theme.option,value:iValue,children:iName},iValue))}}// NOTE: This element represents the current `value` when it does not match
20
+ */import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const Dropdown=({filter,label,onChange,options,testId,theme,value})=>{let isValidValue=false;const optionElements=[];const composed=useTheme("Dropdown",defaultTheme,theme);for(const option of options){if(!filter||filter(option)){const[iValue,iName]=optionValueName(option);isValidValue||=iValue===value;optionElements.push(/*#__PURE__*/_jsx("option",{className:composed.option,value:iValue,children:iName},iValue))}}// NOTE: This element represents the current `value` when it does not match
21
21
  // any valid option. In Chrome, and some other browsers, we are able to hide
22
22
  // it from the opened dropdown; in others, e.g. Safari, the best we can do is
23
23
  // to show it as disabled.
24
- const hiddenOption=isValidValue?null:/*#__PURE__*/_jsx("option",{className:theme.hiddenOption,disabled:true,value:value,children:value},"__reactUtilsHiddenOption");let selectClassName=theme.select;if(!isValidValue)selectClassName+=` ${theme.invalid}`;return/*#__PURE__*/_jsxs("div",{className:theme.container,children:[label===undefined?null:/*#__PURE__*/_jsx("div",{className:theme.label,children:label}),/*#__PURE__*/_jsxs("div",{className:theme.dropdown,children:[/*#__PURE__*/_jsxs("select",{className:selectClassName,"data-testid":process.env.NODE_ENV==="production"?undefined:testId,onChange:onChange,value:value,children:[hiddenOption,optionElements]}),/*#__PURE__*/_jsx("div",{className:theme.arrow})]})]})};export default/* #__PURE__ */themed(Dropdown,"Dropdown",defaultTheme);
24
+ const hiddenOption=isValidValue?null:/*#__PURE__*/_jsx("option",{className:composed.hiddenOption,disabled:true,value:value,children:value},"__reactUtilsHiddenOption");let selectClassName=composed.select;if(!isValidValue)selectClassName+=` ${composed.invalid}`;return/*#__PURE__*/_jsxs("div",{className:composed.container,children:[label===undefined?null:/*#__PURE__*/_jsx("div",{className:composed.label,children:label}),/*#__PURE__*/_jsxs("div",{className:composed.dropdown,children:[/*#__PURE__*/_jsxs("select",{className:selectClassName,"data-testid":process.env.NODE_ENV==="production"?undefined:testId,onChange:onChange,value:value,children:[hiddenOption,optionElements]}),/*#__PURE__*/_jsx("div",{className:composed.arrow})]})]})};export default Dropdown;
25
25
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["themed","optionValueName","defaultTheme","jsx","_jsx","jsxs","_jsxs","Dropdown","filter","label","onChange","options","testId","theme","value","isValidValue","optionElements","option","iValue","iName","push","className","children","hiddenOption","disabled","selectClassName","select","invalid","container","undefined","dropdown","process","env","NODE_ENV","arrow"],"sources":["../../../../../../src/shared/components/selectors/NativeDropdown/index.tsx"],"sourcesContent":["// Implements dropdown based on the native HTML <select> element.\n\nimport themed from '@dr.pogodin/react-themes';\n\nimport { type PropsT, optionValueName } from '../common';\n\nimport defaultTheme from './theme.scss';\n\n/**\n * Implements a themeable dropdown list. Internally it is rendered with help of\n * the standard HTML `<select>` element, thus the styling support is somewhat\n * limited.\n * @param [props] Component properties.\n * @param [props.filter] Options filter function. If provided, only\n * those elements of `options` list will be used by the dropdown, for which this\n * filter returns `true`.\n * @param [props.label] Dropdown label.\n * @param [props.onChange] Selection event handler.\n * @param [props.options=[]] Array of dropdown\n * options. For string elements the option value and name will be the same.\n * It is allowed to mix DropdownOption and string elements in the same option\n * list.\n * @param [props.theme] _Ad hoc_ theme.\n * @param [props.value] Currently selected value.\n * @param [props....]\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)\n */\nconst Dropdown: React.FunctionComponent<PropsT<string>> = ({\n filter,\n label,\n onChange,\n options,\n testId,\n theme,\n value,\n}) => {\n let isValidValue = false;\n const optionElements = [];\n\n for (const option of options) {\n if (!filter || filter(option)) {\n const [iValue, iName] = optionValueName(option);\n isValidValue ||= iValue === value;\n optionElements.push(\n <option className={theme.option} key={iValue} value={iValue}>\n {iName}\n </option>,\n );\n }\n }\n\n // NOTE: This element represents the current `value` when it does not match\n // any valid option. In Chrome, and some other browsers, we are able to hide\n // it from the opened dropdown; in others, e.g. Safari, the best we can do is\n // to show it as disabled.\n const hiddenOption = isValidValue ? null : (\n <option\n className={theme.hiddenOption}\n disabled\n key=\"__reactUtilsHiddenOption\"\n value={value}\n >\n {value}\n </option>\n );\n\n let selectClassName = theme.select;\n if (!isValidValue) selectClassName += ` ${theme.invalid}`;\n\n return (\n <div className={theme.container}>\n { label === undefined\n ? null : <div className={theme.label}>{label}</div> }\n <div className={theme.dropdown}>\n <select\n className={selectClassName}\n data-testid={process.env.NODE_ENV === 'production' ? undefined : testId}\n onChange={onChange}\n value={value}\n >\n {hiddenOption}\n {optionElements}\n </select>\n <div className={theme.arrow} />\n </div>\n </div>\n );\n};\n\nexport default /* #__PURE__ */ themed(Dropdown, 'Dropdown', defaultTheme);\n"],"mappings":"wLAAA;AAEA,MAAO,CAAAA,MAAM,KAAM,0BAA0B,QAEvBC,eAAe,0BAAAC,YAAA,gOAIrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAlBA,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAmBA,KAAM,CAAAC,QAAiD,CAAGA,CAAC,CACzDC,MAAM,CACNC,KAAK,CACLC,QAAQ,CACRC,OAAO,CACPC,MAAM,CACNC,KAAK,CACLC,KACF,CAAC,GAAK,CACJ,GAAI,CAAAC,YAAY,CAAG,KAAK,CACxB,KAAM,CAAAC,cAAc,CAAG,EAAE,CAEzB,IAAK,KAAM,CAAAC,MAAM,GAAI,CAAAN,OAAO,CAAE,CAC5B,GAAI,CAACH,MAAM,EAAIA,MAAM,CAACS,MAAM,CAAC,CAAE,CAC7B,KAAM,CAACC,MAAM,CAAEC,KAAK,CAAC,CAAGlB,eAAe,CAACgB,MAAM,CAAC,CAC/CF,YAAY,GAAKG,MAAM,GAAKJ,KAAK,CACjCE,cAAc,CAACI,IAAI,cACjBhB,IAAA,WAAQiB,SAAS,CAAER,KAAK,CAACI,MAAO,CAAcH,KAAK,CAAEI,MAAO,CAAAI,QAAA,CACzDH,KAAK,EAD8BD,MAE9B,CACV,CACF,CACF,CAEA;AACA;AACA;AACA;AACA,KAAM,CAAAK,YAAY,CAAGR,YAAY,CAAG,IAAI,cACtCX,IAAA,WACEiB,SAAS,CAAER,KAAK,CAACU,YAAa,CAC9BC,QAAQ,MAERV,KAAK,CAAEA,KAAM,CAAAQ,QAAA,CAEZR,KAAK,EAHF,0BAIE,CACT,CAED,GAAI,CAAAW,eAAe,CAAGZ,KAAK,CAACa,MAAM,CAClC,GAAI,CAACX,YAAY,CAAEU,eAAe,EAAI,IAAIZ,KAAK,CAACc,OAAO,EAAE,CAEzD,mBACErB,KAAA,QAAKe,SAAS,CAAER,KAAK,CAACe,SAAU,CAAAN,QAAA,EAC5Bb,KAAK,GAAKoB,SAAS,CACjB,IAAI,cAAGzB,IAAA,QAAKiB,SAAS,CAAER,KAAK,CAACJ,KAAM,CAAAa,QAAA,CAAEb,KAAK,CAAM,CAAC,cACrDH,KAAA,QAAKe,SAAS,CAAER,KAAK,CAACiB,QAAS,CAAAR,QAAA,eAC7BhB,KAAA,WACEe,SAAS,CAAEI,eAAgB,CAC3B,cAAaM,OAAO,CAACC,GAAG,CAACC,QAAQ,GAAK,YAAY,CAAGJ,SAAS,CAAGjB,MAAO,CACxEF,QAAQ,CAAEA,QAAS,CACnBI,KAAK,CAAEA,KAAM,CAAAQ,QAAA,EAEZC,YAAY,CACZP,cAAc,EACT,CAAC,cACTZ,IAAA,QAAKiB,SAAS,CAAER,KAAK,CAACqB,KAAM,CAAE,CAAC,EAC5B,CAAC,EACH,CAET,CAAC,CAED,cAAe,eAAgBlC,MAAM,CAACO,QAAQ,CAAE,UAAU,CAAEL,YAAY,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useTheme","optionValueName","defaultTheme","jsx","_jsx","jsxs","_jsxs","Dropdown","filter","label","onChange","options","testId","theme","value","isValidValue","optionElements","composed","option","iValue","iName","push","className","children","hiddenOption","disabled","selectClassName","select","invalid","container","undefined","dropdown","process","env","NODE_ENV","arrow"],"sources":["../../../../../../src/shared/components/selectors/NativeDropdown/index.tsx"],"sourcesContent":["// Implements dropdown based on the native HTML <select> element.\n\nimport type { FunctionComponent } from 'react';\n\nimport { useTheme } from '@dr.pogodin/react-themes';\n\nimport { optionValueName, type PropsT } from '../common';\n\nimport defaultTheme from './theme.scss';\n\n/**\n * Implements a themeable dropdown list. Internally it is rendered with help of\n * the standard HTML `<select>` element, thus the styling support is somewhat\n * limited.\n * @param [props] Component properties.\n * @param [props.filter] Options filter function. If provided, only\n * those elements of `options` list will be used by the dropdown, for which this\n * filter returns `true`.\n * @param [props.label] Dropdown label.\n * @param [props.onChange] Selection event handler.\n * @param [props.options=[]] Array of dropdown\n * options. For string elements the option value and name will be the same.\n * It is allowed to mix DropdownOption and string elements in the same option\n * list.\n * @param [props.theme] _Ad hoc_ theme.\n * @param [props.value] Currently selected value.\n * @param [props....]\n * [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)\n */\nconst Dropdown: FunctionComponent<PropsT<string>> = ({\n filter,\n label,\n onChange,\n options,\n testId,\n theme,\n value,\n}) => {\n let isValidValue = false;\n const optionElements = [];\n\n const composed = useTheme('Dropdown', defaultTheme, theme);\n\n for (const option of options) {\n if (!filter || filter(option)) {\n const [iValue, iName] = optionValueName(option);\n isValidValue ||= iValue === value;\n optionElements.push(\n <option className={composed.option} key={iValue} value={iValue}>\n {iName}\n </option>,\n );\n }\n }\n\n // NOTE: This element represents the current `value` when it does not match\n // any valid option. In Chrome, and some other browsers, we are able to hide\n // it from the opened dropdown; in others, e.g. Safari, the best we can do is\n // to show it as disabled.\n const hiddenOption = isValidValue ? null : (\n <option\n className={composed.hiddenOption}\n disabled\n key=\"__reactUtilsHiddenOption\"\n value={value}\n >\n {value}\n </option>\n );\n\n let selectClassName = composed.select;\n if (!isValidValue) selectClassName += ` ${composed.invalid}`;\n\n return (\n <div className={composed.container}>\n { label === undefined\n ? null : <div className={composed.label}>{label}</div> }\n <div className={composed.dropdown}>\n <select\n className={selectClassName}\n data-testid={process.env.NODE_ENV === 'production' ? undefined : testId}\n onChange={onChange}\n value={value}\n >\n {hiddenOption}\n {optionElements}\n </select>\n <div className={composed.arrow} />\n </div>\n </div>\n );\n};\n\nexport default Dropdown;\n"],"mappings":"wLAAA;AAIA,OAASA,QAAQ,KAAQ,0BAA0B,QAE1CC,eAAe,0BAAAC,YAAA,gOAIxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAlBA,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAmBA,KAAM,CAAAC,QAA2C,CAAGA,CAAC,CACnDC,MAAM,CACNC,KAAK,CACLC,QAAQ,CACRC,OAAO,CACPC,MAAM,CACNC,KAAK,CACLC,KACF,CAAC,GAAK,CACJ,GAAI,CAAAC,YAAY,CAAG,KAAK,CACxB,KAAM,CAAAC,cAAc,CAAG,EAAE,CAEzB,KAAM,CAAAC,QAAQ,CAAGjB,QAAQ,CAAC,UAAU,CAAEE,YAAY,CAAEW,KAAK,CAAC,CAE1D,IAAK,KAAM,CAAAK,MAAM,GAAI,CAAAP,OAAO,CAAE,CAC5B,GAAI,CAACH,MAAM,EAAIA,MAAM,CAACU,MAAM,CAAC,CAAE,CAC7B,KAAM,CAACC,MAAM,CAAEC,KAAK,CAAC,CAAGnB,eAAe,CAACiB,MAAM,CAAC,CAC/CH,YAAY,GAAKI,MAAM,GAAKL,KAAK,CACjCE,cAAc,CAACK,IAAI,cACjBjB,IAAA,WAAQkB,SAAS,CAAEL,QAAQ,CAACC,MAAO,CAAcJ,KAAK,CAAEK,MAAO,CAAAI,QAAA,CAC5DH,KAAK,EADiCD,MAEjC,CACV,CACF,CACF,CAEA;AACA;AACA;AACA;AACA,KAAM,CAAAK,YAAY,CAAGT,YAAY,CAAG,IAAI,cACtCX,IAAA,WACEkB,SAAS,CAAEL,QAAQ,CAACO,YAAa,CACjCC,QAAQ,MAERX,KAAK,CAAEA,KAAM,CAAAS,QAAA,CAEZT,KAAK,EAHF,0BAIE,CACT,CAED,GAAI,CAAAY,eAAe,CAAGT,QAAQ,CAACU,MAAM,CACrC,GAAI,CAACZ,YAAY,CAAEW,eAAe,EAAI,IAAIT,QAAQ,CAACW,OAAO,EAAE,CAE5D,mBACEtB,KAAA,QAAKgB,SAAS,CAAEL,QAAQ,CAACY,SAAU,CAAAN,QAAA,EAC/Bd,KAAK,GAAKqB,SAAS,CACjB,IAAI,cAAG1B,IAAA,QAAKkB,SAAS,CAAEL,QAAQ,CAACR,KAAM,CAAAc,QAAA,CAAEd,KAAK,CAAM,CAAC,cACxDH,KAAA,QAAKgB,SAAS,CAAEL,QAAQ,CAACc,QAAS,CAAAR,QAAA,eAChCjB,KAAA,WACEgB,SAAS,CAAEI,eAAgB,CAC3B,cAAaM,OAAO,CAACC,GAAG,CAACC,QAAQ,GAAK,YAAY,CAAGJ,SAAS,CAAGlB,MAAO,CACxEF,QAAQ,CAAEA,QAAS,CACnBI,KAAK,CAAEA,KAAM,CAAAS,QAAA,EAEZC,YAAY,CACZR,cAAc,EACT,CAAC,cACTZ,IAAA,QAAKkB,SAAS,CAAEL,QAAQ,CAACkB,KAAM,CAAE,CAAC,EAC/B,CAAC,EACH,CAET,CAAC,CAED,cAAe,CAAA5B,QAAQ","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- import"core-js/modules/es.array.push.js";import themed from"@dr.pogodin/react-themes";import{optionValueName}from"../common.js";const defaultTheme={"context":"akD3dQ","ad":"xcXtdE","hoc":"N3iziJ","container":"BYeWyJ","option":"_7MFXEN","selected":"CDbWAd","options":"_9-eOZo"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";const BaseSwitch=({label,onChange,options,theme,value})=>{if(!options||!theme.option)throw Error("Internal error");const optionNodes=[];for(const option of options){const[iValue,iName]=optionValueName(option);let className=theme.option;let onPress;if(iValue===value)className+=` ${theme.selected}`;else if(onChange){onPress=()=>{onChange(iValue)}}optionNodes.push(onPress?/*#__PURE__*/_jsx("div",{className:className,onClick:onPress,onKeyDown:e=>{if(e.key==="Enter")onPress()},role:"button",tabIndex:0,children:iName},iValue):/*#__PURE__*/_jsx("div",{className:className,children:iName},iValue))}return/*#__PURE__*/_jsxs("div",{className:theme.container,children:[label?/*#__PURE__*/_jsx("div",{className:theme.label,children:label}):null,/*#__PURE__*/_jsx("div",{className:theme.options,children:optionNodes})]})};export default/* #__PURE__ */themed(BaseSwitch,"Switch",defaultTheme);
1
+ import"core-js/modules/es.array.push.js";import{useTheme}from"@dr.pogodin/react-themes";import{optionValueName}from"../common.js";const defaultTheme={"context":"akD3dQ","ad":"xcXtdE","hoc":"N3iziJ","container":"BYeWyJ","option":"_7MFXEN","selected":"CDbWAd","options":"_9-eOZo"};import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export const Switch=({label,onChange,options,theme,value})=>{const composed=useTheme("Switch",defaultTheme,theme);if(!options||!composed.option)throw Error("Internal error");const optionNodes=[];for(const option of options){const[iValue,iName]=optionValueName(option);let className=composed.option;let onPress;if(iValue===value)className+=` ${composed.selected}`;else if(onChange){onPress=()=>{onChange(iValue)}}optionNodes.push(onPress?/*#__PURE__*/_jsx("div",{className:className,onClick:onPress,onKeyDown:e=>{if(e.key==="Enter")onPress()},role:"button",tabIndex:0,children:iName},iValue):/*#__PURE__*/_jsx("div",{className:className,children:iName},iValue))}return/*#__PURE__*/_jsxs("div",{className:composed.container,children:[label?/*#__PURE__*/_jsx("div",{className:composed.label,children:label}):null,/*#__PURE__*/_jsx("div",{className:composed.options,children:optionNodes})]})};
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["themed","optionValueName","defaultTheme","jsx","_jsx","jsxs","_jsxs","BaseSwitch","label","onChange","options","theme","value","option","Error","optionNodes","iValue","iName","className","onPress","selected","push","onClick","onKeyDown","e","key","role","tabIndex","children","container"],"sources":["../../../../../../src/shared/components/selectors/Switch/index.tsx"],"sourcesContent":["import themed, { type Theme } from '@dr.pogodin/react-themes';\n\nimport {\n type OptionsT,\n type ValueT,\n optionValueName,\n} from '../common';\n\nimport defaultTheme from './theme.scss';\n\ntype ThemeKeyT = 'container' | 'label' | 'option' | 'options' | 'selected';\n\ntype PropsT = {\n label?: React.ReactNode;\n onChange?: (value: ValueT) => void;\n options?: Readonly<OptionsT<React.ReactNode>>;\n theme: Theme<ThemeKeyT>;\n value?: ValueT;\n};\n\nconst BaseSwitch: React.FunctionComponent<PropsT> = ({\n label,\n onChange,\n options,\n theme,\n value,\n}) => {\n if (!options || !theme.option) throw Error('Internal error');\n\n const optionNodes: React.ReactNode[] = [];\n for (const option of options) {\n const [iValue, iName] = optionValueName(option);\n\n let className: string = theme.option;\n let onPress: (() => void) | undefined;\n if (iValue === value) className += ` ${theme.selected}`;\n else if (onChange) {\n onPress = () => {\n onChange(iValue);\n };\n }\n\n optionNodes.push(\n onPress\n ? (\n <div\n className={className}\n key={iValue}\n onClick={onPress}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onPress();\n }}\n role=\"button\"\n tabIndex={0}\n >\n {iName}\n </div>\n )\n : <div className={className} key={iValue}>{iName}</div>,\n );\n }\n\n return (\n <div className={theme.container}>\n {label ? <div className={theme.label}>{label}</div> : null}\n\n <div className={theme.options}>\n {optionNodes}\n </div>\n </div>\n );\n};\n\nexport default /* #__PURE__ */ themed(BaseSwitch, 'Switch', defaultTheme);\n"],"mappings":"yCAAA,MAAO,CAAAA,MAAM,KAAsB,0BAA0B,QAK3DC,eAAe,0BAAAC,YAAA,mIAGuB,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAYxC,KAAM,CAAAC,UAA2C,CAAGA,CAAC,CACnDC,KAAK,CACLC,QAAQ,CACRC,OAAO,CACPC,KAAK,CACLC,KACF,CAAC,GAAK,CACJ,GAAI,CAACF,OAAO,EAAI,CAACC,KAAK,CAACE,MAAM,CAAE,KAAM,CAAAC,KAAK,CAAC,gBAAgB,CAAC,CAE5D,KAAM,CAAAC,WAA8B,CAAG,EAAE,CACzC,IAAK,KAAM,CAAAF,MAAM,GAAI,CAAAH,OAAO,CAAE,CAC5B,KAAM,CAACM,MAAM,CAAEC,KAAK,CAAC,CAAGhB,eAAe,CAACY,MAAM,CAAC,CAE/C,GAAI,CAAAK,SAAiB,CAAGP,KAAK,CAACE,MAAM,CACpC,GAAI,CAAAM,OAAiC,CACrC,GAAIH,MAAM,GAAKJ,KAAK,CAAEM,SAAS,EAAI,IAAIP,KAAK,CAACS,QAAQ,EAAE,CAAC,IACnD,IAAIX,QAAQ,CAAE,CACjBU,OAAO,CAAGA,CAAA,GAAM,CACdV,QAAQ,CAACO,MAAM,CACjB,CACF,CAEAD,WAAW,CAACM,IAAI,CACdF,OAAO,cAEHf,IAAA,QACEc,SAAS,CAAEA,SAAU,CAErBI,OAAO,CAAEH,OAAQ,CACjBI,SAAS,CAAGC,CAAC,EAAK,CAChB,GAAIA,CAAC,CAACC,GAAG,GAAK,OAAO,CAAEN,OAAO,CAAC,CACjC,CAAE,CACFO,IAAI,CAAC,QAAQ,CACbC,QAAQ,CAAE,CAAE,CAAAC,QAAA,CAEXX,KAAK,EARDD,MASF,CAAC,cAENZ,IAAA,QAAKc,SAAS,CAAEA,SAAU,CAAAU,QAAA,CAAeX,KAAK,EAAdD,MAAoB,CAC1D,CACF,CAEA,mBACEV,KAAA,QAAKY,SAAS,CAAEP,KAAK,CAACkB,SAAU,CAAAD,QAAA,EAC7BpB,KAAK,cAAGJ,IAAA,QAAKc,SAAS,CAAEP,KAAK,CAACH,KAAM,CAAAoB,QAAA,CAAEpB,KAAK,CAAM,CAAC,CAAG,IAAI,cAE1DJ,IAAA,QAAKc,SAAS,CAAEP,KAAK,CAACD,OAAQ,CAAAkB,QAAA,CAC3Bb,WAAW,CACT,CAAC,EACH,CAET,CAAC,CAED,cAAe,eAAgBf,MAAM,CAACO,UAAU,CAAE,QAAQ,CAAEL,YAAY,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["useTheme","optionValueName","defaultTheme","jsx","_jsx","jsxs","_jsxs","Switch","label","onChange","options","theme","value","composed","option","Error","optionNodes","iValue","iName","className","onPress","selected","push","onClick","onKeyDown","e","key","role","tabIndex","children","container"],"sources":["../../../../../../src/shared/components/selectors/Switch/index.tsx"],"sourcesContent":["import type { FunctionComponent, ReactNode } from 'react';\n\nimport { type Theme, useTheme } from '@dr.pogodin/react-themes';\n\nimport {\n type OptionsT,\n type ValueT,\n optionValueName,\n} from '../common';\n\nimport defaultTheme from './theme.scss';\n\ntype ThemeT = Theme<'container' | 'label' | 'option' | 'options' | 'selected'>;\n\ntype PropsT = {\n label?: ReactNode;\n onChange?: (value: ValueT) => void;\n options?: Readonly<OptionsT<ReactNode>>;\n theme?: ThemeT;\n value?: ValueT;\n};\n\nexport const Switch: FunctionComponent<PropsT> = ({\n label,\n onChange,\n options,\n theme,\n value,\n}) => {\n const composed = useTheme('Switch', defaultTheme, theme);\n\n if (!options || !composed.option) throw Error('Internal error');\n\n const optionNodes: React.ReactNode[] = [];\n for (const option of options) {\n const [iValue, iName] = optionValueName(option);\n\n let className: string = composed.option;\n let onPress: (() => void) | undefined;\n if (iValue === value) className += ` ${composed.selected}`;\n else if (onChange) {\n onPress = () => {\n onChange(iValue);\n };\n }\n\n optionNodes.push(\n onPress\n ? (\n <div\n className={className}\n key={iValue}\n onClick={onPress}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onPress();\n }}\n role=\"button\"\n tabIndex={0}\n >\n {iName}\n </div>\n )\n : <div className={className} key={iValue}>{iName}</div>,\n );\n }\n\n return (\n <div className={composed.container}>\n {label ? <div className={composed.label}>{label}</div> : null}\n\n <div className={composed.options}>\n {optionNodes}\n </div>\n </div>\n );\n};\n"],"mappings":"yCAEA,OAAqBA,QAAQ,KAAQ,0BAA0B,QAK7DC,eAAe,0BAAAC,YAAA,mIAGuB,OAAAC,GAAA,IAAAC,IAAA,CAAAC,IAAA,IAAAC,KAAA,yBAYxC,MAAO,MAAM,CAAAC,MAAiC,CAAGA,CAAC,CAChDC,KAAK,CACLC,QAAQ,CACRC,OAAO,CACPC,KAAK,CACLC,KACF,CAAC,GAAK,CACJ,KAAM,CAAAC,QAAQ,CAAGb,QAAQ,CAAC,QAAQ,CAAEE,YAAY,CAAES,KAAK,CAAC,CAExD,GAAI,CAACD,OAAO,EAAI,CAACG,QAAQ,CAACC,MAAM,CAAE,KAAM,CAAAC,KAAK,CAAC,gBAAgB,CAAC,CAE/D,KAAM,CAAAC,WAA8B,CAAG,EAAE,CACzC,IAAK,KAAM,CAAAF,MAAM,GAAI,CAAAJ,OAAO,CAAE,CAC5B,KAAM,CAACO,MAAM,CAAEC,KAAK,CAAC,CAAGjB,eAAe,CAACa,MAAM,CAAC,CAE/C,GAAI,CAAAK,SAAiB,CAAGN,QAAQ,CAACC,MAAM,CACvC,GAAI,CAAAM,OAAiC,CACrC,GAAIH,MAAM,GAAKL,KAAK,CAAEO,SAAS,EAAI,IAAIN,QAAQ,CAACQ,QAAQ,EAAE,CAAC,IACtD,IAAIZ,QAAQ,CAAE,CACjBW,OAAO,CAAGA,CAAA,GAAM,CACdX,QAAQ,CAACQ,MAAM,CACjB,CACF,CAEAD,WAAW,CAACM,IAAI,CACdF,OAAO,cAEHhB,IAAA,QACEe,SAAS,CAAEA,SAAU,CAErBI,OAAO,CAAEH,OAAQ,CACjBI,SAAS,CAAGC,CAAC,EAAK,CAChB,GAAIA,CAAC,CAACC,GAAG,GAAK,OAAO,CAAEN,OAAO,CAAC,CACjC,CAAE,CACFO,IAAI,CAAC,QAAQ,CACbC,QAAQ,CAAE,CAAE,CAAAC,QAAA,CAEXX,KAAK,EARDD,MASF,CAAC,cAENb,IAAA,QAAKe,SAAS,CAAEA,SAAU,CAAAU,QAAA,CAAeX,KAAK,EAAdD,MAAoB,CAC1D,CACF,CAEA,mBACEX,KAAA,QAAKa,SAAS,CAAEN,QAAQ,CAACiB,SAAU,CAAAD,QAAA,EAChCrB,KAAK,cAAGJ,IAAA,QAAKe,SAAS,CAAEN,QAAQ,CAACL,KAAM,CAAAqB,QAAA,CAAErB,KAAK,CAAM,CAAC,CAAG,IAAI,cAE7DJ,IAAA,QAAKe,SAAS,CAAEN,QAAQ,CAACH,OAAQ,CAAAmB,QAAA,CAC9Bb,WAAW,CACT,CAAC,EACH,CAET,CAAC","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\ntype ThemeKeyT = '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\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: Theme<ThemeKeyT>;\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;AA4CA,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":[]}
@@ -1,2 +1,2 @@
1
- export{default as CustomDropdown}from"./CustomDropdown/index.js";export{default as Dropdown}from"./NativeDropdown/index.js";export{default as Switch}from"./Switch/index.js";
1
+ export{default as CustomDropdown}from"./CustomDropdown/index.js";export{default as Dropdown}from"./NativeDropdown/index.js";export{Switch}from"./Switch/index.js";
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["default","CustomDropdown","Dropdown","Switch"],"sources":["../../../../../src/shared/components/selectors/index.ts"],"sourcesContent":["export { default as CustomDropdown } from './CustomDropdown';\nexport { default as Dropdown } from './NativeDropdown';\nexport { default as Switch } from './Switch';\n\nexport {\n type OptionT,\n type OptionsT,\n} from './common';\n"],"mappings":"OAASA,OAAO,GAAI,CAAAC,cAAc,wCACzBD,OAAO,GAAI,CAAAE,QAAQ,wCACnBF,OAAO,GAAI,CAAAG,MAAM","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["default","CustomDropdown","Dropdown","Switch"],"sources":["../../../../../src/shared/components/selectors/index.ts"],"sourcesContent":["export { default as CustomDropdown } from './CustomDropdown';\nexport { default as Dropdown } from './NativeDropdown';\nexport { Switch } from './Switch';\n\nexport type { OptionT, OptionsT } from './common';\n"],"mappings":"OAASA,OAAO,GAAI,CAAAC,cAAc,wCACzBD,OAAO,GAAI,CAAAE,QAAQ,wCACnBC,MAAM","ignoreList":[]}
@@ -1,2 +1,2 @@
1
- import themedImpl,{COMPOSE,PRIORITY,ThemeProvider}from"@dr.pogodin/react-themes";import{getConfig}from"./config.js";import*as isomorphy from"./isomorphy/index.js";import time from"./time.js";import*as webpack from"./webpack.js";export{assertEmptyObject,Barrier,Cached,Emitter,Semaphore,withRetries}from"@dr.pogodin/js-utils";export{getSsrContext}from"./globalState.js";export{default as splitComponent}from"./splitComponent.js";const themed=themedImpl;themed.COMPOSE=COMPOSE;themed.PRIORITY=PRIORITY;export{getConfig,isomorphy,themed,ThemeProvider,time,webpack};
1
+ import{getConfig}from"./config.js";import*as isomorphy from"./isomorphy/index.js";import time from"./time.js";import*as webpack from"./webpack.js";export{assertEmptyObject,Barrier,Cached,Emitter,Semaphore,withRetries}from"@dr.pogodin/js-utils";export{COMPOSE as THEME_COMPOSE,PRIORITY as THEME_PRIORITY,ThemeProvider,useTheme}from"@dr.pogodin/react-themes";export{getSsrContext}from"./globalState.js";export{default as splitComponent}from"./splitComponent.js";export{getConfig,isomorphy,time,webpack};
2
2
  //# sourceMappingURL=index.js.map