@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,5 +1,5 @@
1
1
  import { useEffect, useLayoutEffect, useRef, useState } from 'react';
2
- import themed from '@dr.pogodin/react-themes';
2
+ import { useTheme } from '@dr.pogodin/react-themes';
3
3
  const defaultTheme = {
4
4
  "context": "-dr-pogodin-react-utils___build-web-shared-components-TextArea-style___context___tECG8C",
5
5
  "ad": "-dr-pogodin-react-utils___build-web-shared-components-TextArea-style___ad___epeH4O",
@@ -24,6 +24,7 @@ const TextArea = ({
24
24
  theme,
25
25
  value
26
26
  }) => {
27
+ const custom = useTheme('TextArea', defaultTheme, theme);
27
28
  const hiddenAreaRef = useRef(null);
28
29
  const [height, setHeight] = useState();
29
30
  const textAreaRef = useRef(null);
@@ -55,18 +56,18 @@ const TextArea = ({
55
56
  const el = hiddenAreaRef.current;
56
57
  if (el) setHeight(el.scrollHeight);
57
58
  }, [localValue]);
58
- let containerClassName = theme.container;
59
- if (error) containerClassName += ` ${theme.error}`;
59
+ let containerClassName = custom.container;
60
+ if (error) containerClassName += ` ${custom.error}`;
60
61
  return /*#__PURE__*/_jsxs("div", {
61
62
  className: containerClassName,
62
63
  onFocus: () => {
63
64
  textAreaRef.current?.focus();
64
65
  },
65
66
  children: [label === undefined ? null : /*#__PURE__*/_jsx("div", {
66
- className: theme.label,
67
+ className: custom.label,
67
68
  children: label
68
69
  }), /*#__PURE__*/_jsx("textarea", {
69
- className: `${theme.textarea} ${theme.hidden}`
70
+ className: `${custom.textarea} ${custom.hidden}`
70
71
 
71
72
  // This text area is hidden underneath the primary one below,
72
73
  // and it is used for text measurements, to implement auto-scaling
@@ -90,7 +91,7 @@ const TextArea = ({
90
91
 
91
92
  value: localValue || ' '
92
93
  }), /*#__PURE__*/_jsx("textarea", {
93
- className: theme.textarea,
94
+ className: custom.textarea,
94
95
  "data-testid": process.env.NODE_ENV === 'production' ? undefined : testId,
95
96
  disabled: disabled,
96
97
  onBlur: onBlur
@@ -111,10 +112,10 @@ const TextArea = ({
111
112
  },
112
113
  value: localValue
113
114
  }), error && error !== true ? /*#__PURE__*/_jsx("div", {
114
- className: theme.errorMessage,
115
+ className: custom.errorMessage,
115
116
  children: error
116
117
  }) : null]
117
118
  });
118
119
  };
119
- export default /* #__PURE__ */themed(TextArea, 'TextArea', defaultTheme);
120
+ export default TextArea;
120
121
  //# 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":"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","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":"AAAA,SAMEA,SAAS,EACTC,eAAe,EACfC,MAAM,EACNC,QAAQ,QACH,OAAO;AAEd,SAAqBC,QAAQ,QAAQ,0BAA0B;AAAA,MAAAC,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAEvB,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAkBxC,MAAMC,QAAkC,GAAGA,CAAC;EAC1CC,QAAQ;EACRC,KAAK;EACLC,KAAK;EACLC,MAAM;EACNC,QAAQ;EACRC,SAAS;EACTC,WAAW;EACXC,MAAM;EACNC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,MAAMC,MAAM,GAAGjB,QAAQ,CAAC,UAAU,EAAEC,YAAY,EAAEc,KAAK,CAAC;EAExD,MAAMG,aAAa,GAAGpB,MAAM,CAAsB,IAAI,CAAC;EACvD,MAAM,CAACqB,MAAM,EAAEC,SAAS,CAAC,GAAGrB,QAAQ,CAAqB,CAAC;EAE1D,MAAMsB,WAAW,GAAGvB,MAAM,CAAsB,IAAI,CAAC;EAErD,MAAM,CAACwB,UAAU,EAAEC,aAAa,CAAC,GAAGxB,QAAQ,CAACiB,KAAK,IAAI,EAAE,CAAC;EACzD,IAAIA,KAAK,KAAKQ,SAAS,IAAIF,UAAU,KAAKN,KAAK,EAAEO,aAAa,CAACP,KAAK,CAAC;;EAErE;EACApB,SAAS,CAAC,MAAM;IACd,MAAM6B,EAAE,GAAGP,aAAa,CAACQ,OAAO;IAChC,IAAI,CAACD,EAAE,EAAE,OAAOD,SAAS;IAEzB,MAAMG,EAAE,GAAGA,CAAA,KAAM;MACfP,SAAS,CAACK,EAAE,CAACG,YAAY,CAAC;IAC5B,CAAC;IACD,MAAMC,QAAQ,GAAG,IAAIC,cAAc,CAACH,EAAE,CAAC;IACvCE,QAAQ,CAACE,OAAO,CAACN,EAAE,CAAC;IAEpB,OAAO,MAAM;MACXI,QAAQ,CAACG,UAAU,CAAC,CAAC;IACvB,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;;EAEN;EACA;EACA;EACA;EACA;EACA;EACA;EACAnC,eAAe,CAAC,MAAM;IACpB,MAAM4B,EAAE,GAAGP,aAAa,CAACQ,OAAO;IAChC,IAAID,EAAE,EAAEL,SAAS,CAACK,EAAE,CAACG,YAAY,CAAC;EACpC,CAAC,EAAE,CAACN,UAAU,CAAC,CAAC;EAEhB,IAAIW,kBAAkB,GAAGhB,MAAM,CAACiB,SAAS;EACzC,IAAI1B,KAAK,EAAEyB,kBAAkB,IAAI,IAAIhB,MAAM,CAACT,KAAK,EAAE;EAEnD,oBACEH,KAAA;IACE8B,SAAS,EAAEF,kBAAmB;IAC9BG,OAAO,EAAEA,CAAA,KAAM;MACbf,WAAW,CAACK,OAAO,EAAEW,KAAK,CAAC,CAAC;IAC9B,CAAE;IAAAC,QAAA,GAED7B,KAAK,KAAKe,SAAS,GAAG,IAAI,gBAAGrB,IAAA;MAAKgC,SAAS,EAAElB,MAAM,CAACR,KAAM;MAAA6B,QAAA,EAAE7B;IAAK,CAAM,CAAC,eACzEN,IAAA;MACEgC,SAAS,EAAE,GAAGlB,MAAM,CAACsB,QAAQ,IAAItB,MAAM,CAACuB,MAAM;;MAE9C;MACA;MACA;MAAA;;MACAC,QAAQ;MACRC,GAAG,EAAExB;;MAEL;MACA;MAAA;;MACAyB,QAAQ,EAAE,CAAC;;MAEX;MACA;MACA;MACA;MAAA;;MACA3B,KAAK,EAAEM,UAAU,IAAI;IAAI,CAC1B,CAAC,eACFnB,IAAA;MACEgC,SAAS,EAAElB,MAAM,CAACsB,QAAS;MAC3B,eAAaK,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,GAAGtB,SAAS,GAAGV,MAAO;MACxEP,QAAQ,EAAEA,QAAS;MACnBG,MAAM,EAAEA;;MAER;MACA;MACA;MAAA;;MACAC,QAAQ,EACNK,KAAK,KAAKQ,SAAS,GACduB,CAAC,IAAK;QACPxB,aAAa,CAACwB,CAAC,CAACC,MAAM,CAAChC,KAAK,CAAC;MAC/B,CAAC,GAAGL,QACP;MACDC,SAAS,EAAEA,SAAU;MACrBC,WAAW,EAAEA,WAAY;MACzB6B,GAAG,EAAErB,WAAY;MACjB4B,KAAK,EAAE;QAAE9B;MAAO,CAAE;MAClBH,KAAK,EAAEM;IAAW,CACnB,CAAC,EACDd,KAAK,IAAIA,KAAK,KAAK,IAAI,gBACpBL,IAAA;MAAKgC,SAAS,EAAElB,MAAM,CAACiC,YAAa;MAAAZ,QAAA,EAAE9B;IAAK,CAAM,CAAC,GAClD,IAAI;EAAA,CACL,CAAC;AAEV,CAAC;AAED,eAAeF,QAAQ","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- import themed from '@dr.pogodin/react-themes';
1
+ import { useTheme } from '@dr.pogodin/react-themes';
2
2
  const defaultTheme = {
3
3
  "context": "-dr-pogodin-react-utils___build-web-shared-components-Throbber-theme___context___eVCJf-",
4
4
  "ad": "-dr-pogodin-react-utils___build-web-shared-components-Throbber-theme___ad___CU2B6H",
@@ -19,15 +19,18 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
19
  */
20
20
  const Throbber = ({
21
21
  theme
22
- }) => /*#__PURE__*/_jsxs("span", {
23
- className: theme.container,
24
- children: [/*#__PURE__*/_jsx("span", {
25
- className: theme.circle
26
- }), /*#__PURE__*/_jsx("span", {
27
- className: theme.circle
28
- }), /*#__PURE__*/_jsx("span", {
29
- className: theme.circle
30
- })]
31
- });
32
- export default /* #__PURE__ */themed(Throbber, 'Throbber', defaultTheme);
22
+ }) => {
23
+ const custom = useTheme('Throbber', defaultTheme, theme);
24
+ return /*#__PURE__*/_jsxs("span", {
25
+ className: custom.container,
26
+ children: [/*#__PURE__*/_jsx("span", {
27
+ className: custom.circle
28
+ }), /*#__PURE__*/_jsx("span", {
29
+ className: custom.circle
30
+ }), /*#__PURE__*/_jsx("span", {
31
+ className: custom.circle
32
+ })]
33
+ });
34
+ };
35
+ export default Throbber;
33
36
  //# 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,OAAOA,MAAM,MAAsB,0BAA0B;AAAA,MAAAC,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAErB,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAQxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,QAAyC,GAAGA,CAAC;EAAEC;AAAM,CAAC,kBAC1DF,KAAA;EAAMG,SAAS,EAAED,KAAK,CAACE,SAAU;EAAAC,QAAA,gBAC/BP,IAAA;IAAMK,SAAS,EAAED,KAAK,CAACI;EAAO,CAAE,CAAC,eACjCR,IAAA;IAAMK,SAAS,EAAED,KAAK,CAACI;EAAO,CAAE,CAAC,eACjCR,IAAA;IAAMK,SAAS,EAAED,KAAK,CAACI;EAAO,CAAE,CAAC;AAAA,CAC7B,CACP;AAED,eAAe,eAAgBX,MAAM,CAACM,QAAQ,EAAE,UAAU,EAAEL,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,SAAqBA,QAAQ,QAAQ,0BAA0B;AAAA,MAAAC,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAEvB,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAQxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,QAAmC,GAAGA,CAAC;EAAEC;AAAM,CAAC,KAAK;EACzD,MAAMC,MAAM,GAAGR,QAAQ,CAAC,UAAU,EAAEC,YAAY,EAAEM,KAAK,CAAC;EAExD,oBACEF,KAAA;IAAMI,SAAS,EAAED,MAAM,CAACE,SAAU;IAAAC,QAAA,gBAChCR,IAAA;MAAMM,SAAS,EAAED,MAAM,CAACI;IAAO,CAAE,CAAC,eAClCT,IAAA;MAAMM,SAAS,EAAED,MAAM,CAACI;IAAO,CAAE,CAAC,eAClCT,IAAA;MAAMM,SAAS,EAAED,MAAM,CAACI;IAAO,CAAE,CAAC;EAAA,CAC9B,CAAC;AAEX,CAAC;AAED,eAAeN,QAAQ","ignoreList":[]}
@@ -1,7 +1,7 @@
1
1
  /* global window */
2
2
 
3
3
  import { useEffect, useRef, useState } from 'react';
4
- import themed from '@dr.pogodin/react-themes';
4
+ import { useTheme } from '@dr.pogodin/react-themes';
5
5
  import Tooltip, { PLACEMENTS } from "./Tooltip.js";
6
6
  const defaultTheme = {
7
7
  "ad": "-dr-pogodin-react-utils___build-web-shared-components-WithTooltip-default-theme___ad___n6OiU9",
@@ -27,12 +27,13 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
27
27
  * _e.g._ a tooltip text. This will be the tooltip content.
28
28
  * @param {WithTooltipTheme} props.theme _Ad hoc_ theme.
29
29
  */
30
- const Wrapper = ({
30
+ const WithTooltip = ({
31
31
  children,
32
32
  placement = PLACEMENTS.ABOVE_CURSOR,
33
33
  tip,
34
34
  theme
35
35
  }) => {
36
+ const custom = useTheme('WithTooltip', defaultTheme, theme);
36
37
  const {
37
38
  current: heap
38
39
  } = useRef({
@@ -92,7 +93,7 @@ const Wrapper = ({
92
93
  return undefined;
93
94
  }, [heap.lastCursorX, heap.lastCursorY, placement, showTooltip, tip]);
94
95
  return /*#__PURE__*/_jsxs("div", {
95
- className: theme.wrapper,
96
+ className: custom.wrapper,
96
97
  onClick: () => {
97
98
  if (heap.timerId) {
98
99
  clearTimeout(heap.timerId);
@@ -113,13 +114,12 @@ const Wrapper = ({
113
114
  role: "presentation",
114
115
  children: [showTooltip && tip !== null ? /*#__PURE__*/_jsx(Tooltip, {
115
116
  ref: tooltipRef,
116
- theme: theme,
117
+ theme: custom,
117
118
  children: tip
118
119
  }) : null, children]
119
120
  });
120
121
  };
121
- const ThemedWrapper = /* #__PURE__ */themed(Wrapper, 'WithTooltip', defaultTheme);
122
- const e = ThemedWrapper;
122
+ const e = WithTooltip;
123
123
  e.PLACEMENTS = PLACEMENTS;
124
124
  export default e;
125
125
  //# 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":"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","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,7 +1,7 @@
1
1
  import qs from 'qs';
2
- import themed from '@dr.pogodin/react-themes';
2
+ import { useTheme } from '@dr.pogodin/react-themes';
3
3
  import Throbber from "../Throbber/index.js";
4
- const baseTheme = {
4
+ const defaultTheme = {
5
5
  "context": "-dr-pogodin-react-utils___build-web-shared-components-YouTubeVideo-base___context___Pa7GiX",
6
6
  "ad": "-dr-pogodin-react-utils___build-web-shared-components-YouTubeVideo-base___ad___NikZ57",
7
7
  "hoc": "-dr-pogodin-react-utils___build-web-shared-components-YouTubeVideo-base___hoc___FydyFQ",
@@ -36,6 +36,7 @@ const YouTubeVideo = ({
36
36
  theme,
37
37
  title
38
38
  }) => {
39
+ const custom = useTheme('YouTubeVideo', defaultTheme, theme);
39
40
  const srcParts = src.split('?');
40
41
  let [url] = srcParts;
41
42
  const [, queryString] = srcParts;
@@ -50,18 +51,18 @@ const YouTubeVideo = ({
50
51
  // More query parameters can be exposed via the component props.
51
52
 
52
53
  return /*#__PURE__*/_jsxs("div", {
53
- className: theme.container,
54
+ className: custom.container,
54
55
  children: [/*#__PURE__*/_jsx(Throbber, {
55
56
  theme: throbberTheme
56
57
  }), /*#__PURE__*/_jsx("iframe", {
57
58
  // eslint-disable-line react/iframe-missing-sandbox
58
59
  allow: "autoplay",
59
60
  allowFullScreen: true,
60
- className: theme.video,
61
+ className: custom.video,
61
62
  src: url,
62
63
  title: title
63
64
  })]
64
65
  });
65
66
  };
66
- export default /* #__PURE__ */themed(YouTubeVideo, 'YouTubeVideo', baseTheme);
67
+ export default YouTubeVideo;
67
68
  //# 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,OAAOA,EAAE,MAAM,IAAI;AAEnB,OAAOC,MAAM,MAAsB,0BAA0B;AAAA,OAEtDC,QAAQ;AAAA,MAAAC,SAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAAA,MAAAC,aAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAG6B,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAW5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,YAA6C,GAAGA,CAAC;EACrDC,QAAQ;EACRC,GAAG;EACHC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,MAAMC,QAAQ,GAAGH,GAAG,CAACI,KAAK,CAAC,GAAG,CAAC;EAC/B,IAAI,CAACC,GAAG,CAAC,GAAGF,QAAQ;EACpB,MAAM,GAAGG,WAAW,CAAC,GAAGH,QAAQ;EAChC,MAAMI,KAAK,GAAGD,WAAW,GAAGjB,EAAE,CAACmB,KAAK,CAACF,WAAW,CAAC,GAAG,CAAC,CAAC;EAEtD,MAAMG,OAAO,GAAGF,KAAK,CAACG,CAAC,IAAIL,GAAG,EAAEM,KAAK,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;EACjEN,GAAG,GAAG,iCAAiCI,OAAO,EAAY;EAE1D,OAAOF,KAAK,CAACG,CAAC;EACdH,KAAK,CAACR,QAAQ,GAAGA,QAAQ,GAAG,GAAG,GAAG,GAAG;EACrCM,GAAG,IAAI,IAAIhB,EAAE,CAACuB,SAAS,CAACL,KAAK,CAAC,EAAE;;EAEhC;EACA;;EAEA,oBACEV,KAAA;IAAKgB,SAAS,EAAEZ,KAAK,CAACa,SAAU;IAAAC,QAAA,gBAC9BpB,IAAA,CAACJ,QAAQ;MAACU,KAAK,EAAER;IAAc,CAAE,CAAC,eAKlCE,IAAA;MAAQ;MACNqB,KAAK,EAAC,UAAU;MAChBC,eAAe;MACfJ,SAAS,EAAEZ,KAAK,CAACiB,KAAM;MACvBlB,GAAG,EAAEK,GAAI;MACTH,KAAK,EAAEA;IAAM,CACd,CAAC;EAAA,CACC,CAAC;AAEV,CAAC;AAED,eAAe,eAAgBZ,MAAM,CAACQ,YAAY,EAAE,cAAc,EAAEN,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,OAAOA,EAAE,MAAM,IAAI;AAGnB,SAAqBC,QAAQ,QAAQ,0BAA0B;AAAA,OAExDC,QAAQ;AAAA,MAAAC,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAAA,MAAAC,aAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAG6B,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAW5C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,YAAuC,GAAGA,CAAC;EAC/CC,QAAQ;EACRC,GAAG;EACHC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,MAAMC,MAAM,GAAGb,QAAQ,CAAC,cAAc,EAAEE,YAAY,EAAES,KAAK,CAAC;EAE5D,MAAMG,QAAQ,GAAGJ,GAAG,CAACK,KAAK,CAAC,GAAG,CAAC;EAC/B,IAAI,CAACC,GAAG,CAAC,GAAGF,QAAQ;EACpB,MAAM,GAAGG,WAAW,CAAC,GAAGH,QAAQ;EAChC,MAAMI,KAAK,GAAGD,WAAW,GAAGlB,EAAE,CAACoB,KAAK,CAACF,WAAW,CAAC,GAAG,CAAC,CAAC;EAEtD,MAAMG,OAAO,GAAGF,KAAK,CAACG,CAAC,IAAIL,GAAG,EAAEM,KAAK,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;EACjEN,GAAG,GAAG,iCAAiCI,OAAO,EAAY;EAE1D,OAAOF,KAAK,CAACG,CAAC;EACdH,KAAK,CAACT,QAAQ,GAAGA,QAAQ,GAAG,GAAG,GAAG,GAAG;EACrCO,GAAG,IAAI,IAAIjB,EAAE,CAACwB,SAAS,CAACL,KAAK,CAAC,EAAE;;EAEhC;EACA;;EAEA,oBACEX,KAAA;IAAKiB,SAAS,EAAEX,MAAM,CAACY,SAAU;IAAAC,QAAA,gBAC/BrB,IAAA,CAACJ,QAAQ;MAACU,KAAK,EAAER;IAAc,CAAE,CAAC,eAKlCE,IAAA;MAAQ;MACNsB,KAAK,EAAC,UAAU;MAChBC,eAAe;MACfJ,SAAS,EAAEX,MAAM,CAACgB,KAAM;MACxBnB,GAAG,EAAEM,GAAI;MACTJ,KAAK,EAAEA;IAAM,CACd,CAAC;EAAA,CACC,CAAC;AAEV,CAAC;AAED,eAAeJ,YAAY","ignoreList":[]}
@@ -2,7 +2,7 @@ import "core-js/modules/es.iterator.filter.js";
2
2
  import "core-js/modules/es.iterator.constructor.js";
3
3
  import "core-js/modules/es.iterator.filter.js";
4
4
  import { useEffect, useRef, useState } from 'react';
5
- import themed from '@dr.pogodin/react-themes';
5
+ import { useTheme } from '@dr.pogodin/react-themes';
6
6
  import { optionValueName } from "../common.js";
7
7
  import Options, { areEqual } from "./Options/index.js";
8
8
  const defaultTheme = {
@@ -19,7 +19,7 @@ const defaultTheme = {
19
19
  "upward": "-dr-pogodin-react-utils___build-web-shared-components-selectors-CustomDropdown-theme___upward___--5Xpy"
20
20
  };
21
21
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
- const BaseCustomDropdown = ({
22
+ const CustomDropdown = ({
23
23
  filter,
24
24
  label,
25
25
  onChange,
@@ -27,6 +27,7 @@ const BaseCustomDropdown = ({
27
27
  theme,
28
28
  value
29
29
  }) => {
30
+ const custom = useTheme('CustomDropdown', defaultTheme, theme);
30
31
  const [active, setActive] = useState(false);
31
32
  const dropdownRef = useRef(null);
32
33
  const opsRef = useRef(null);
@@ -91,20 +92,20 @@ const BaseCustomDropdown = ({
91
92
  }
92
93
  }
93
94
  }
94
- let containerClassName = theme.container;
95
- if (active) containerClassName += ` ${theme.active}`;
96
- let opsContainerClass = theme.select ?? '';
95
+ let containerClassName = custom.container;
96
+ if (active) containerClassName += ` ${custom.active}`;
97
+ let opsContainerClass = custom.select ?? '';
97
98
  if (upward) {
98
- containerClassName += ` ${theme.upward}`;
99
- opsContainerClass += ` ${theme.upward}`;
99
+ containerClassName += ` ${custom.upward}`;
100
+ opsContainerClass += ` ${custom.upward}`;
100
101
  }
101
102
  return /*#__PURE__*/_jsxs("div", {
102
103
  className: containerClassName,
103
104
  children: [label === undefined ? null : /*#__PURE__*/_jsx("div", {
104
- className: theme.label,
105
+ className: custom.label,
105
106
  children: label
106
107
  }), /*#__PURE__*/_jsxs("div", {
107
- className: theme.dropdown,
108
+ className: custom.dropdown,
108
109
  onClick: openList,
109
110
  onKeyDown: e => {
110
111
  if (e.key === 'Enter') openList(e);
@@ -113,7 +114,7 @@ const BaseCustomDropdown = ({
113
114
  role: "listbox",
114
115
  tabIndex: 0,
115
116
  children: [selected, /*#__PURE__*/_jsx("div", {
116
- className: theme.arrow
117
+ className: custom.arrow
117
118
  })]
118
119
  }), active ? /*#__PURE__*/_jsx(Options, {
119
120
  containerClass: opsContainerClass,
@@ -125,11 +126,11 @@ const BaseCustomDropdown = ({
125
126
  setActive(false);
126
127
  if (onChange) onChange(newValue);
127
128
  },
128
- optionClass: theme.option ?? '',
129
+ optionClass: custom.option ?? '',
129
130
  options: options,
130
131
  ref: opsRef
131
132
  }) : null]
132
133
  });
133
134
  };
134
- export default /* #__PURE__ */themed(BaseCustomDropdown, 'CustomDropdown', defaultTheme);
135
+ export default CustomDropdown;
135
136
  //# 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":";;;AAAA,SAGEA,SAAS,EACTC,MAAM,EACNC,QAAQ,QACH,OAAO;AAEd,SAASC,QAAQ,QAAQ,0BAA0B;AAAA,SAEhBC,eAAe;AAAA,OAE3CC,OAAO,IAAmCC,QAAQ;AAAA,MAAAC,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAEjB,SAAAC,QAAA,IAAAC,SAAA,EAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAExC,MAAMC,cAEL,GAAGA,CAAC;EACHC,MAAM;EACNC,KAAK;EACLC,QAAQ;EACRC,OAAO;EACPC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,MAAMC,MAAM,GAAGlB,QAAQ,CAAC,gBAAgB,EAAEI,YAAY,EAAEY,KAAK,CAAC;EAE9D,MAAM,CAACG,MAAM,EAAEC,SAAS,CAAC,GAAGrB,QAAQ,CAAC,KAAK,CAAC;EAE3C,MAAMsB,WAAW,GAAGvB,MAAM,CAAiB,IAAI,CAAC;EAChD,MAAMwB,MAAM,GAAGxB,MAAM,CAAO,IAAI,CAAC;EAEjC,MAAM,CAACyB,MAAM,EAAEC,SAAS,CAAC,GAAGzB,QAAQ,CAAgB,CAAC;EACrD,MAAM,CAAC0B,MAAM,EAAEC,SAAS,CAAC,GAAG3B,QAAQ,CAAC,KAAK,CAAC;EAE3CF,SAAS,CAAC,MAAM;IACd,IAAI,CAACsB,MAAM,EAAE,OAAOQ,SAAS;IAE7B,IAAIC,EAAU;IACd,MAAMC,EAAE,GAAGA,CAAA,KAAM;MACf,MAAMC,MAAM,GAAGT,WAAW,CAACU,OAAO,EAAEC,qBAAqB,CAAC,CAAC;MAC3D,MAAMC,OAAO,GAAGX,MAAM,CAACS,OAAO,EAAEG,OAAO,CAAC,CAAC;MACzC,IAAIJ,MAAM,IAAIG,OAAO,EAAE;QACrB,MAAME,QAAQ,GAAGL,MAAM,CAACM,MAAM,GAAGH,OAAO,CAACI,MAAM,IAC1CC,MAAM,CAACC,cAAc,EAAEF,MAAM,IAAI,CAAC,CAAC;QACxC,MAAMG,MAAM,GAAGV,MAAM,CAACW,GAAG,GAAGR,OAAO,CAACI,MAAM,GAAG,CAAC;QAE9C,MAAMK,EAAE,GAAG,CAACP,QAAQ,IAAIK,MAAM;QAC9Bd,SAAS,CAACgB,EAAE,CAAC;QAEb,MAAMC,GAAG,GAAGD,EAAE,GAAG;UACfE,IAAI,EAAEd,MAAM,CAACc,IAAI;UACjBH,GAAG,EAAEX,MAAM,CAACW,GAAG,GAAGR,OAAO,CAACI,MAAM,GAAG,CAAC;UACpCQ,KAAK,EAAEf,MAAM,CAACe;QAChB,CAAC,GAAG;UACFD,IAAI,EAAEd,MAAM,CAACc,IAAI;UACjBH,GAAG,EAAEX,MAAM,CAACM,MAAM;UAClBS,KAAK,EAAEf,MAAM,CAACe;QAChB,CAAC;QAEDrB,SAAS,CAAEsB,GAAG,IAAM3C,QAAQ,CAAC2C,GAAG,EAAEH,GAAG,CAAC,GAAGG,GAAG,GAAGH,GAAI,CAAC;MACtD;MACAf,EAAE,GAAGmB,qBAAqB,CAAClB,EAAE,CAAC;IAChC,CAAC;IACDkB,qBAAqB,CAAClB,EAAE,CAAC;IAEzB,OAAO,MAAM;MACXmB,oBAAoB,CAACpB,EAAE,CAAC;IAC1B,CAAC;EACH,CAAC,EAAE,CAACT,MAAM,CAAC,CAAC;EAEZ,MAAM8B,QAAQ,GACZC,CAAyE,IACtE;IACH,MAAMC,IAAI,GAAGb,MAAM,CAACC,cAAc;IAClC,MAAMa,IAAI,GAAG/B,WAAW,CAACU,OAAO,CAAEC,qBAAqB,CAAC,CAAC;IACzDZ,SAAS,CAAC,IAAI,CAAC;;IAEf;IACA;IACA;IACA;IACA;IACA;IACAI,SAAS,CAAC;MACRoB,IAAI,EAAEO,IAAI,EAAEN,KAAK,IAAI,CAAC;MACtBJ,GAAG,EAAEU,IAAI,EAAEd,MAAM,IAAI,CAAC;MACtBQ,KAAK,EAAEO,IAAI,CAACP;IACd,CAAC,CAAC;IAEFK,CAAC,CAACG,eAAe,CAAC,CAAC;EACrB,CAAC;EAED,IAAIC,QAAyB,gBAAG9C,IAAA,CAAAF,SAAA;IAAAiD,QAAA,EAAE;EAAM,CAAE,CAAC;EAC3C,KAAK,MAAMC,MAAM,IAAIzC,OAAO,EAAE;IAC5B,IAAI,CAACH,MAAM,IAAIA,MAAM,CAAC4C,MAAM,CAAC,EAAE;MAC7B,MAAM,CAACC,MAAM,EAAEC,KAAK,CAAC,GAAGzD,eAAe,CAACuD,MAAM,CAAC;MAC/C,IAAIC,MAAM,KAAKxC,KAAK,EAAE;QACpBqC,QAAQ,GAAGI,KAAK;QAChB;MACF;IACF;EACF;EAEA,IAAIC,kBAAkB,GAAGzC,MAAM,CAAC0C,SAAS;EACzC,IAAIzC,MAAM,EAAEwC,kBAAkB,IAAI,IAAIzC,MAAM,CAACC,MAAM,EAAE;EAErD,IAAI0C,iBAAiB,GAAG3C,MAAM,CAAC4C,MAAM,IAAI,EAAE;EAC3C,IAAIrC,MAAM,EAAE;IACVkC,kBAAkB,IAAI,IAAIzC,MAAM,CAACO,MAAM,EAAE;IACzCoC,iBAAiB,IAAI,IAAI3C,MAAM,CAACO,MAAM,EAAE;EAC1C;EAEA,oBACEf,KAAA;IAAKqD,SAAS,EAAEJ,kBAAmB;IAAAJ,QAAA,GAChC1C,KAAK,KAAKc,SAAS,GAAG,IAAI,gBACvBnB,IAAA;MAAKuD,SAAS,EAAE7C,MAAM,CAACL,KAAM;MAAA0C,QAAA,EAAE1C;IAAK,CAAM,CAAC,eAC/CH,KAAA;MACEqD,SAAS,EAAE7C,MAAM,CAAC8C,QAAS;MAC3BC,OAAO,EAAEhB,QAAS;MAClBiB,SAAS,EAAGhB,CAAC,IAAK;QAChB,IAAIA,CAAC,CAACiB,GAAG,KAAK,OAAO,EAAElB,QAAQ,CAACC,CAAC,CAAC;MACpC,CAAE;MACFkB,GAAG,EAAE/C,WAAY;MACjBgD,IAAI,EAAC,SAAS;MACdC,QAAQ,EAAE,CAAE;MAAAf,QAAA,GAEXD,QAAQ,eACT9C,IAAA;QAAKuD,SAAS,EAAE7C,MAAM,CAACqD;MAAM,CAAE,CAAC;IAAA,CAC7B,CAAC,EAEJpD,MAAM,gBACJX,IAAA,CAACN,OAAO;MACNsE,cAAc,EAAEX,iBAAkB;MAClCY,cAAc,EAAElD,MAAO;MACvBmD,QAAQ,EAAEA,CAAA,KAAM;QACdtD,SAAS,CAAC,KAAK,CAAC;MAClB,CAAE;MACFN,QAAQ,EAAG6D,QAAQ,IAAK;QACtBvD,SAAS,CAAC,KAAK,CAAC;QAChB,IAAIN,QAAQ,EAAEA,QAAQ,CAAC6D,QAAQ,CAAC;MAClC,CAAE;MACFC,WAAW,EAAE1D,MAAM,CAACsC,MAAM,IAAI,EAAG;MACjCzC,OAAO,EAAEA,OAAQ;MACjBqD,GAAG,EAAE9C;IAAO,CACb,CAAC,GACA,IAAI;EAAA,CAEP,CAAC;AAEV,CAAC;AAED,eAAeX,cAAc","ignoreList":[]}
@@ -4,7 +4,7 @@ import "core-js/modules/es.iterator.constructor.js";
4
4
  import "core-js/modules/es.iterator.filter.js";
5
5
  // Implements dropdown based on the native HTML <select> element.
6
6
 
7
- import themed from '@dr.pogodin/react-themes';
7
+ import { useTheme } from '@dr.pogodin/react-themes';
8
8
  import { optionValueName } from "../common.js";
9
9
  const defaultTheme = {
10
10
  "context": "-dr-pogodin-react-utils___build-web-shared-components-selectors-NativeDropdown-theme___context___WbwY1Y",
@@ -51,12 +51,13 @@ const Dropdown = ({
51
51
  }) => {
52
52
  let isValidValue = false;
53
53
  const optionElements = [];
54
+ const composed = useTheme('Dropdown', defaultTheme, theme);
54
55
  for (const option of options) {
55
56
  if (!filter || filter(option)) {
56
57
  const [iValue, iName] = optionValueName(option);
57
58
  isValidValue ||= iValue === value;
58
59
  optionElements.push(/*#__PURE__*/_jsx("option", {
59
- className: theme.option,
60
+ className: composed.option,
60
61
  value: iValue,
61
62
  children: iName
62
63
  }, iValue));
@@ -68,20 +69,20 @@ const Dropdown = ({
68
69
  // it from the opened dropdown; in others, e.g. Safari, the best we can do is
69
70
  // to show it as disabled.
70
71
  const hiddenOption = isValidValue ? null : /*#__PURE__*/_jsx("option", {
71
- className: theme.hiddenOption,
72
+ className: composed.hiddenOption,
72
73
  disabled: true,
73
74
  value: value,
74
75
  children: value
75
76
  }, "__reactUtilsHiddenOption");
76
- let selectClassName = theme.select;
77
- if (!isValidValue) selectClassName += ` ${theme.invalid}`;
77
+ let selectClassName = composed.select;
78
+ if (!isValidValue) selectClassName += ` ${composed.invalid}`;
78
79
  return /*#__PURE__*/_jsxs("div", {
79
- className: theme.container,
80
+ className: composed.container,
80
81
  children: [label === undefined ? null : /*#__PURE__*/_jsx("div", {
81
- className: theme.label,
82
+ className: composed.label,
82
83
  children: label
83
84
  }), /*#__PURE__*/_jsxs("div", {
84
- className: theme.dropdown,
85
+ className: composed.dropdown,
85
86
  children: [/*#__PURE__*/_jsxs("select", {
86
87
  className: selectClassName,
87
88
  "data-testid": process.env.NODE_ENV === 'production' ? undefined : testId,
@@ -89,10 +90,10 @@ const Dropdown = ({
89
90
  value: value,
90
91
  children: [hiddenOption, optionElements]
91
92
  }), /*#__PURE__*/_jsx("div", {
92
- className: theme.arrow
93
+ className: composed.arrow
93
94
  })]
94
95
  })]
95
96
  });
96
97
  };
97
- export default /* #__PURE__ */themed(Dropdown, 'Dropdown', defaultTheme);
98
+ export default Dropdown;
98
99
  //# 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":";;;;AAAA;;AAEA,OAAOA,MAAM,MAAM,0BAA0B;AAAA,SAEvBC,eAAe;AAAA,MAAAC,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAIrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAlBA,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAmBA,MAAMC,QAAiD,GAAGA,CAAC;EACzDC,MAAM;EACNC,KAAK;EACLC,QAAQ;EACRC,OAAO;EACPC,MAAM;EACNC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,IAAIC,YAAY,GAAG,KAAK;EACxB,MAAMC,cAAc,GAAG,EAAE;EAEzB,KAAK,MAAMC,MAAM,IAAIN,OAAO,EAAE;IAC5B,IAAI,CAACH,MAAM,IAAIA,MAAM,CAACS,MAAM,CAAC,EAAE;MAC7B,MAAM,CAACC,MAAM,EAAEC,KAAK,CAAC,GAAGlB,eAAe,CAACgB,MAAM,CAAC;MAC/CF,YAAY,KAAKG,MAAM,KAAKJ,KAAK;MACjCE,cAAc,CAACI,IAAI,cACjBhB,IAAA;QAAQiB,SAAS,EAAER,KAAK,CAACI,MAAO;QAAcH,KAAK,EAAEI,MAAO;QAAAI,QAAA,EACzDH;MAAK,GAD8BD,MAE9B,CACV,CAAC;IACH;EACF;;EAEA;EACA;EACA;EACA;EACA,MAAMK,YAAY,GAAGR,YAAY,GAAG,IAAI,gBACtCX,IAAA;IACEiB,SAAS,EAAER,KAAK,CAACU,YAAa;IAC9BC,QAAQ;IAERV,KAAK,EAAEA,KAAM;IAAAQ,QAAA,EAEZR;EAAK,GAHF,0BAIE,CACT;EAED,IAAIW,eAAe,GAAGZ,KAAK,CAACa,MAAM;EAClC,IAAI,CAACX,YAAY,EAAEU,eAAe,IAAI,IAAIZ,KAAK,CAACc,OAAO,EAAE;EAEzD,oBACErB,KAAA;IAAKe,SAAS,EAAER,KAAK,CAACe,SAAU;IAAAN,QAAA,GAC5Bb,KAAK,KAAKoB,SAAS,GACjB,IAAI,gBAAGzB,IAAA;MAAKiB,SAAS,EAAER,KAAK,CAACJ,KAAM;MAAAa,QAAA,EAAEb;IAAK,CAAM,CAAC,eACrDH,KAAA;MAAKe,SAAS,EAAER,KAAK,CAACiB,QAAS;MAAAR,QAAA,gBAC7BhB,KAAA;QACEe,SAAS,EAAEI,eAAgB;QAC3B,eAAaM,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,GAAGJ,SAAS,GAAGjB,MAAO;QACxEF,QAAQ,EAAEA,QAAS;QACnBI,KAAK,EAAEA,KAAM;QAAAQ,QAAA,GAEZC,YAAY,EACZP,cAAc;MAAA,CACT,CAAC,eACTZ,IAAA;QAAKiB,SAAS,EAAER,KAAK,CAACqB;MAAM,CAAE,CAAC;IAAA,CAC5B,CAAC;EAAA,CACH,CAAC;AAEV,CAAC;AAED,eAAe,eAAgBlC,MAAM,CAACO,QAAQ,EAAE,UAAU,EAAEL,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":";;;;AAAA;;AAIA,SAASA,QAAQ,QAAQ,0BAA0B;AAAA,SAE1CC,eAAe;AAAA,MAAAC,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAIxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAlBA,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAmBA,MAAMC,QAA2C,GAAGA,CAAC;EACnDC,MAAM;EACNC,KAAK;EACLC,QAAQ;EACRC,OAAO;EACPC,MAAM;EACNC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,IAAIC,YAAY,GAAG,KAAK;EACxB,MAAMC,cAAc,GAAG,EAAE;EAEzB,MAAMC,QAAQ,GAAGjB,QAAQ,CAAC,UAAU,EAAEE,YAAY,EAAEW,KAAK,CAAC;EAE1D,KAAK,MAAMK,MAAM,IAAIP,OAAO,EAAE;IAC5B,IAAI,CAACH,MAAM,IAAIA,MAAM,CAACU,MAAM,CAAC,EAAE;MAC7B,MAAM,CAACC,MAAM,EAAEC,KAAK,CAAC,GAAGnB,eAAe,CAACiB,MAAM,CAAC;MAC/CH,YAAY,KAAKI,MAAM,KAAKL,KAAK;MACjCE,cAAc,CAACK,IAAI,cACjBjB,IAAA;QAAQkB,SAAS,EAAEL,QAAQ,CAACC,MAAO;QAAcJ,KAAK,EAAEK,MAAO;QAAAI,QAAA,EAC5DH;MAAK,GADiCD,MAEjC,CACV,CAAC;IACH;EACF;;EAEA;EACA;EACA;EACA;EACA,MAAMK,YAAY,GAAGT,YAAY,GAAG,IAAI,gBACtCX,IAAA;IACEkB,SAAS,EAAEL,QAAQ,CAACO,YAAa;IACjCC,QAAQ;IAERX,KAAK,EAAEA,KAAM;IAAAS,QAAA,EAEZT;EAAK,GAHF,0BAIE,CACT;EAED,IAAIY,eAAe,GAAGT,QAAQ,CAACU,MAAM;EACrC,IAAI,CAACZ,YAAY,EAAEW,eAAe,IAAI,IAAIT,QAAQ,CAACW,OAAO,EAAE;EAE5D,oBACEtB,KAAA;IAAKgB,SAAS,EAAEL,QAAQ,CAACY,SAAU;IAAAN,QAAA,GAC/Bd,KAAK,KAAKqB,SAAS,GACjB,IAAI,gBAAG1B,IAAA;MAAKkB,SAAS,EAAEL,QAAQ,CAACR,KAAM;MAAAc,QAAA,EAAEd;IAAK,CAAM,CAAC,eACxDH,KAAA;MAAKgB,SAAS,EAAEL,QAAQ,CAACc,QAAS;MAAAR,QAAA,gBAChCjB,KAAA;QACEgB,SAAS,EAAEI,eAAgB;QAC3B,eAAaM,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,GAAGJ,SAAS,GAAGlB,MAAO;QACxEF,QAAQ,EAAEA,QAAS;QACnBI,KAAK,EAAEA,KAAM;QAAAS,QAAA,GAEZC,YAAY,EACZR,cAAc;MAAA,CACT,CAAC,eACTZ,IAAA;QAAKkB,SAAS,EAAEL,QAAQ,CAACkB;MAAM,CAAE,CAAC;IAAA,CAC/B,CAAC;EAAA,CACH,CAAC;AAEV,CAAC;AAED,eAAe5B,QAAQ","ignoreList":[]}
@@ -1,5 +1,5 @@
1
1
  import "core-js/modules/es.array.push.js";
2
- import themed from '@dr.pogodin/react-themes';
2
+ import { useTheme } from '@dr.pogodin/react-themes';
3
3
  import { optionValueName } from "../common.js";
4
4
  const defaultTheme = {
5
5
  "context": "-dr-pogodin-react-utils___build-web-shared-components-selectors-Switch-theme___context___akD3dQ",
@@ -11,20 +11,21 @@ const defaultTheme = {
11
11
  "options": "-dr-pogodin-react-utils___build-web-shared-components-selectors-Switch-theme___options___9-eOZo"
12
12
  };
13
13
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
- const BaseSwitch = ({
14
+ export const Switch = ({
15
15
  label,
16
16
  onChange,
17
17
  options,
18
18
  theme,
19
19
  value
20
20
  }) => {
21
- if (!options || !theme.option) throw Error('Internal error');
21
+ const composed = useTheme('Switch', defaultTheme, theme);
22
+ if (!options || !composed.option) throw Error('Internal error');
22
23
  const optionNodes = [];
23
24
  for (const option of options) {
24
25
  const [iValue, iName] = optionValueName(option);
25
- let className = theme.option;
26
+ let className = composed.option;
26
27
  let onPress;
27
- if (iValue === value) className += ` ${theme.selected}`;else if (onChange) {
28
+ if (iValue === value) className += ` ${composed.selected}`;else if (onChange) {
28
29
  onPress = () => {
29
30
  onChange(iValue);
30
31
  };
@@ -44,15 +45,14 @@ const BaseSwitch = ({
44
45
  }, iValue));
45
46
  }
46
47
  return /*#__PURE__*/_jsxs("div", {
47
- className: theme.container,
48
+ className: composed.container,
48
49
  children: [label ? /*#__PURE__*/_jsx("div", {
49
- className: theme.label,
50
+ className: composed.label,
50
51
  children: label
51
52
  }) : null, /*#__PURE__*/_jsx("div", {
52
- className: theme.options,
53
+ className: composed.options,
53
54
  children: optionNodes
54
55
  })]
55
56
  });
56
57
  };
57
- export default /* #__PURE__ */themed(BaseSwitch, 'Switch', defaultTheme);
58
58
  //# sourceMappingURL=index.js.map