@dr.pogodin/react-utils 1.38.0 → 1.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/development/index.js +0 -9
- package/build/development/index.js.map +1 -1
- package/build/development/shared/components/Button/index.js +4 -0
- package/build/development/shared/components/Button/index.js.map +1 -1
- package/build/development/shared/components/Input/index.js +2 -0
- package/build/development/shared/components/Input/index.js.map +1 -1
- package/build/development/shared/components/Modal/index.js +4 -1
- package/build/development/shared/components/Modal/index.js.map +1 -1
- package/build/development/shared/components/selectors/NativeDropdown/index.js +2 -0
- package/build/development/shared/components/selectors/NativeDropdown/index.js.map +1 -1
- package/build/development/shared/components/selectors/common.js.map +1 -1
- package/build/development/shared/utils/jest/index.js +31 -0
- package/build/development/shared/utils/jest/index.js.map +1 -1
- package/build/development/style.css +8 -8
- package/build/development/web.bundle.js +10 -20
- package/build/production/index.js +1 -1
- package/build/production/index.js.map +1 -1
- package/build/production/shared/components/Button/index.js +1 -1
- package/build/production/shared/components/Button/index.js.map +1 -1
- package/build/production/shared/components/Input/index.js +1 -1
- package/build/production/shared/components/Input/index.js.map +1 -1
- package/build/production/shared/components/Modal/index.js +2 -2
- package/build/production/shared/components/Modal/index.js.map +1 -1
- package/build/production/shared/components/selectors/NativeDropdown/index.js +2 -2
- package/build/production/shared/components/selectors/NativeDropdown/index.js.map +1 -1
- package/build/production/shared/components/selectors/common.js.map +1 -1
- package/build/production/shared/utils/jest/index.js +4 -3
- package/build/production/shared/utils/jest/index.js.map +1 -1
- package/build/production/style.css +1 -1
- package/build/production/style.css.map +1 -1
- package/build/production/web.bundle.js +1 -1
- package/build/production/web.bundle.js.map +1 -1
- package/build/types-code/index.d.ts +0 -1
- package/build/types-code/shared/components/Button/index.d.ts +1 -0
- package/build/types-code/shared/components/Input/index.d.ts +1 -0
- package/build/types-code/shared/components/Modal/index.d.ts +4 -1
- package/build/types-code/shared/components/selectors/common.d.ts +1 -0
- package/build/types-code/shared/utils/jest/index.d.ts +4 -0
- package/package.json +6 -6
- package/src/index.ts +0 -2
- package/src/shared/components/Button/index.tsx +5 -1
- package/src/shared/components/Input/index.tsx +3 -0
- package/src/shared/components/Modal/index.tsx +9 -2
- package/src/shared/components/Throbber/theme.scss +5 -5
- package/src/shared/components/selectors/NativeDropdown/index.tsx +2 -0
- package/src/shared/components/selectors/common.ts +1 -0
- package/src/shared/utils/jest/index.tsx +48 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
3
|
Object.defineProperty(exports, "__esModule", {
|
|
5
4
|
value: true
|
|
6
5
|
});
|
|
@@ -19,7 +18,6 @@ var _exportNames = {
|
|
|
19
18
|
time: true,
|
|
20
19
|
webpack: true,
|
|
21
20
|
withRetries: true,
|
|
22
|
-
api: true,
|
|
23
21
|
getGlobalState: true,
|
|
24
22
|
GlobalStateProvider: true,
|
|
25
23
|
newAsyncDataEnvelope: true,
|
|
@@ -58,12 +56,6 @@ Object.defineProperty(exports, "ThemeProvider", {
|
|
|
58
56
|
return _utils.ThemeProvider;
|
|
59
57
|
}
|
|
60
58
|
});
|
|
61
|
-
Object.defineProperty(exports, "api", {
|
|
62
|
-
enumerable: true,
|
|
63
|
-
get: function () {
|
|
64
|
-
return _axios.default;
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
59
|
exports.client = void 0;
|
|
68
60
|
Object.defineProperty(exports, "config", {
|
|
69
61
|
enumerable: true,
|
|
@@ -151,7 +143,6 @@ Object.defineProperty(exports, "withRetries", {
|
|
|
151
143
|
}
|
|
152
144
|
});
|
|
153
145
|
var _utils = require("./shared/utils");
|
|
154
|
-
var _axios = _interopRequireDefault(require("axios"));
|
|
155
146
|
var _reactGlobalState = require("@dr.pogodin/react-global-state");
|
|
156
147
|
var _components = require("./shared/components");
|
|
157
148
|
Object.keys(_components).forEach(function (key) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_utils","require","
|
|
1
|
+
{"version":3,"file":"index.js","names":["_utils","require","_reactGlobalState","_components","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","server","webpack","requireWeak","__dirname","client","undefined","default"],"sources":["../../src/index.ts"],"sourcesContent":["import 'styles/global.scss';\n\nimport { webpack } from 'utils';\n\nimport type ServerT from './server';\n\nconst server = webpack.requireWeak('./server', __dirname) as (typeof ServerT) | null;\n\nconst client = server ? undefined : require('./client').default;\n\nexport {\n type AsyncCollectionLoaderT,\n type AsyncDataEnvelopeT,\n type AsyncDataLoaderT,\n type ForceT,\n type UseAsyncDataOptionsT,\n type UseAsyncDataResT,\n type UseGlobalStateResT,\n type ValueOrInitializerT,\n getGlobalState,\n GlobalStateProvider,\n newAsyncDataEnvelope,\n useAsyncCollection,\n useAsyncData,\n useGlobalState,\n withGlobalStateType,\n} from '@dr.pogodin/react-global-state';\n\nexport * from 'components';\n\nexport {\n type Listener,\n type Theme,\n config,\n Barrier,\n Emitter,\n isomorphy,\n getSsrContext,\n Semaphore,\n splitComponent,\n themed,\n ThemeProvider,\n time,\n webpack,\n withRetries,\n} from 'utils';\n\nexport { client, server };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,IAAAA,MAAA,GAAAC,OAAA;AAQA,IAAAC,iBAAA,GAAAD,OAAA;AAkBA,IAAAE,WAAA,GAAAF,OAAA;AAAAG,MAAA,CAAAC,IAAA,CAAAF,WAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAJ,WAAA,CAAAI,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAZ,WAAA,CAAAI,GAAA;IAAA;EAAA;AAAA;AAtBA,MAAMS,MAAM,GAAAJ,OAAA,CAAAI,MAAA,GAAGC,cAAO,CAACC,WAAW,aAAaC,SAAS,CAA4B;AAEpF,MAAMC,MAAM,GAAAR,OAAA,CAAAQ,MAAA,GAAGJ,MAAM,GAAGK,SAAS,GAAGpB,OAAO,WAAW,CAAC,CAACqB,OAAO","ignoreList":[]}
|
|
@@ -28,6 +28,7 @@ const BaseButton = ({
|
|
|
28
28
|
onMouseDown,
|
|
29
29
|
openNewTab,
|
|
30
30
|
replace,
|
|
31
|
+
testId,
|
|
31
32
|
theme,
|
|
32
33
|
to
|
|
33
34
|
}) => {
|
|
@@ -37,12 +38,14 @@ const BaseButton = ({
|
|
|
37
38
|
if (theme.disabled) className += ` ${theme.disabled}`;
|
|
38
39
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
39
40
|
className: className,
|
|
41
|
+
"data-testid": testId,
|
|
40
42
|
children: children
|
|
41
43
|
});
|
|
42
44
|
}
|
|
43
45
|
if (to) {
|
|
44
46
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Link.default, {
|
|
45
47
|
className: className,
|
|
48
|
+
"data-testid": testId,
|
|
46
49
|
enforceA: enforceA,
|
|
47
50
|
onClick: onClick,
|
|
48
51
|
onMouseDown: onMouseDown,
|
|
@@ -54,6 +57,7 @@ const BaseButton = ({
|
|
|
54
57
|
}
|
|
55
58
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
56
59
|
className: className,
|
|
60
|
+
"data-testid": testId,
|
|
57
61
|
onClick: onClick,
|
|
58
62
|
onKeyDown: onClick && (e => {
|
|
59
63
|
if (e.key === 'Enter') onClick(e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["require","_Link","_interopRequireDefault","_reactThemes","_jsxRuntime","defaultTheme","BaseButton","active","children","disabled","enforceA","onClick","onMouseDown","openNewTab","replace","theme","to","className","button","jsx","default","onKeyDown","e","key","role","tabIndex","exports","_default","themed"],"sources":["../../../../../src/shared/components/Button/index.tsx"],"sourcesContent":["// The <Button> component implements a standard button / button-like link.\n\nimport { type ReactNode } from 'react';\n\nimport Link from 'components/Link';\n\nimport themed, { type Theme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './style.scss';\n\ntype PropsT = {\n active?: boolean;\n children?: ReactNode;\n disabled?: boolean;\n enforceA?: boolean;\n onClick?: React.MouseEventHandler & React.KeyboardEventHandler;\n onMouseDown?: React.MouseEventHandler;\n openNewTab?: boolean;\n replace?: boolean;\n theme: Theme<'active' | 'button' | 'disabled'>;\n // TODO: It needs a more precise typing of the object option.\n to?: object | string;\n};\n\n/* eslint-disable react/function-component-definition */\nexport const BaseButton: React.FunctionComponent<PropsT> = ({\n active,\n children,\n disabled,\n enforceA,\n onClick,\n onMouseDown,\n openNewTab,\n replace,\n theme,\n to,\n}) => {\n let className = theme.button;\n if (active && theme.active) className += ` ${theme.active}`;\n if (disabled) {\n if (theme.disabled) className += ` ${theme.disabled}`;\n return (\n <div className={className}>\n {children}\n </div>\n );\n }\n if (to) {\n return (\n <Link\n className={className}\n enforceA={enforceA}\n onClick={onClick}\n onMouseDown={onMouseDown}\n openNewTab={openNewTab}\n replace={replace}\n to={to}\n >\n {children}\n </Link>\n );\n }\n\n return (\n <div\n className={className}\n onClick={onClick}\n onKeyDown={onClick && ((e) => {\n if (e.key === 'Enter') onClick(e);\n })}\n onMouseDown={onMouseDown}\n role=\"button\"\n tabIndex={0}\n >\n {children}\n </div>\n );\n};\n\n/**\n * Button component theme: a map of CSS\n * class names to append to button elements:\n * @prop {string} [active] to the root element of active button.\n * @prop {string} [button] to the root element of any button.\n * @prop {string} [disabled] to the root element of disabled button.\n */\nexport default themed(BaseButton, 'Button', defaultTheme);\n"],"mappings":";;;;;;;AAEAA,OAAA;AAEA,IAAAC,KAAA,GAAAC,sBAAA,CAAAF,OAAA;AAEA,IAAAG,YAAA,GAAAD,sBAAA,CAAAF,OAAA;AAA8D,IAAAI,WAAA,GAAAJ,OAAA;AAN9D;AAAA,MAAAK,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;
|
|
1
|
+
{"version":3,"file":"index.js","names":["require","_Link","_interopRequireDefault","_reactThemes","_jsxRuntime","defaultTheme","BaseButton","active","children","disabled","enforceA","onClick","onMouseDown","openNewTab","replace","testId","theme","to","className","button","jsx","default","onKeyDown","e","key","role","tabIndex","exports","_default","themed"],"sources":["../../../../../src/shared/components/Button/index.tsx"],"sourcesContent":["// The <Button> component implements a standard button / button-like link.\n\nimport { type ReactNode } from 'react';\n\nimport Link from 'components/Link';\n\nimport themed, { type Theme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './style.scss';\n\ntype PropsT = {\n active?: boolean;\n children?: ReactNode;\n disabled?: boolean;\n enforceA?: boolean;\n onClick?: React.MouseEventHandler & React.KeyboardEventHandler;\n onMouseDown?: React.MouseEventHandler;\n openNewTab?: boolean;\n replace?: boolean;\n testId?: string;\n theme: Theme<'active' | 'button' | 'disabled'>;\n // TODO: It needs a more precise typing of the object option.\n to?: object | string;\n};\n\n/* eslint-disable react/function-component-definition */\nexport const BaseButton: React.FunctionComponent<PropsT> = ({\n active,\n children,\n disabled,\n enforceA,\n onClick,\n onMouseDown,\n openNewTab,\n replace,\n testId,\n theme,\n to,\n}) => {\n let className = theme.button;\n if (active && theme.active) className += ` ${theme.active}`;\n if (disabled) {\n if (theme.disabled) className += ` ${theme.disabled}`;\n return (\n <div className={className} data-testid={testId}>\n {children}\n </div>\n );\n }\n if (to) {\n return (\n <Link\n className={className}\n data-testid={testId}\n enforceA={enforceA}\n onClick={onClick}\n onMouseDown={onMouseDown}\n openNewTab={openNewTab}\n replace={replace}\n to={to}\n >\n {children}\n </Link>\n );\n }\n\n return (\n <div\n className={className}\n data-testid={testId}\n onClick={onClick}\n onKeyDown={onClick && ((e) => {\n if (e.key === 'Enter') onClick(e);\n })}\n onMouseDown={onMouseDown}\n role=\"button\"\n tabIndex={0}\n >\n {children}\n </div>\n );\n};\n\n/**\n * Button component theme: a map of CSS\n * class names to append to button elements:\n * @prop {string} [active] to the root element of active button.\n * @prop {string} [button] to the root element of any button.\n * @prop {string} [disabled] to the root element of disabled button.\n */\nexport default themed(BaseButton, 'Button', defaultTheme);\n"],"mappings":";;;;;;;AAEAA,OAAA;AAEA,IAAAC,KAAA,GAAAC,sBAAA,CAAAF,OAAA;AAEA,IAAAG,YAAA,GAAAD,sBAAA,CAAAF,OAAA;AAA8D,IAAAI,WAAA,GAAAJ,OAAA;AAN9D;AAAA,MAAAK,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAyBA;AACO,MAAMC,UAA2C,GAAGA,CAAC;EAC1DC,MAAM;EACNC,QAAQ;EACRC,QAAQ;EACRC,QAAQ;EACRC,OAAO;EACPC,WAAW;EACXC,UAAU;EACVC,OAAO;EACPC,MAAM;EACNC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,IAAIC,SAAS,GAAGF,KAAK,CAACG,MAAM;EAC5B,IAAIZ,MAAM,IAAIS,KAAK,CAACT,MAAM,EAAEW,SAAS,IAAI,IAAIF,KAAK,CAACT,MAAM,EAAE;EAC3D,IAAIE,QAAQ,EAAE;IACZ,IAAIO,KAAK,CAACP,QAAQ,EAAES,SAAS,IAAI,IAAIF,KAAK,CAACP,QAAQ,EAAE;IACrD,oBACE,IAAAL,WAAA,CAAAgB,GAAA;MAAKF,SAAS,EAAEA,SAAU;MAAC,eAAaH,MAAO;MAAAP,QAAA,EAC5CA;IAAQ,CACN,CAAC;EAEV;EACA,IAAIS,EAAE,EAAE;IACN,oBACE,IAAAb,WAAA,CAAAgB,GAAA,EAACnB,KAAA,CAAAoB,OAAI;MACHH,SAAS,EAAEA,SAAU;MACrB,eAAaH,MAAO;MACpBL,QAAQ,EAAEA,QAAS;MACnBC,OAAO,EAAEA,OAAQ;MACjBC,WAAW,EAAEA,WAAY;MACzBC,UAAU,EAAEA,UAAW;MACvBC,OAAO,EAAEA,OAAQ;MACjBG,EAAE,EAAEA,EAAG;MAAAT,QAAA,EAENA;IAAQ,CACL,CAAC;EAEX;EAEA,oBACE,IAAAJ,WAAA,CAAAgB,GAAA;IACEF,SAAS,EAAEA,SAAU;IACrB,eAAaH,MAAO;IACpBJ,OAAO,EAAEA,OAAQ;IACjBW,SAAS,EAAEX,OAAO,KAAMY,CAAC,IAAK;MAC5B,IAAIA,CAAC,CAACC,GAAG,KAAK,OAAO,EAAEb,OAAO,CAACY,CAAC,CAAC;IACnC,CAAC,CAAE;IACHX,WAAW,EAAEA,WAAY;IACzBa,IAAI,EAAC,QAAQ;IACbC,QAAQ,EAAE,CAAE;IAAAlB,QAAA,EAEXA;EAAQ,CACN,CAAC;AAEV,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AANAmB,OAAA,CAAArB,UAAA,GAAAA,UAAA;AAAA,IAAAsB,QAAA,GAAAD,OAAA,CAAAN,OAAA,GAOe,IAAAQ,oBAAM,EAACvB,UAAU,EAAE,QAAQ,EAAED,YAAY,CAAC","ignoreList":[]}
|
|
@@ -27,6 +27,7 @@ const defaultTheme = {
|
|
|
27
27
|
*/
|
|
28
28
|
const Input = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
29
29
|
label,
|
|
30
|
+
testId,
|
|
30
31
|
theme,
|
|
31
32
|
...rest
|
|
32
33
|
}, ref) => /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
|
|
@@ -36,6 +37,7 @@ const Input = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
|
36
37
|
children: label
|
|
37
38
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
|
|
38
39
|
className: theme.input,
|
|
40
|
+
"data-testid": testId,
|
|
39
41
|
ref: ref,
|
|
40
42
|
...rest
|
|
41
43
|
})]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_react","require","_reactThemes","_interopRequireDefault","_jsxRuntime","defaultTheme","Input","forwardRef","label","theme","rest","ref","jsxs","className","container","children","undefined","jsx","input","_default","exports","default","themed"],"sources":["../../../../../src/shared/components/Input/index.tsx"],"sourcesContent":["import { forwardRef } from 'react';\n\nimport themed, { type Theme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './theme.scss';\n\ntype ThemeKeyT =\n | 'container'\n | 'input'\n | 'label';\n\ntype PropsT = React.InputHTMLAttributes<HTMLInputElement> & {\n label?: React.ReactNode;\n theme: Theme<ThemeKeyT>;\n};\n\n/**\n * Themeable input field, based on the standard HTML `<input>` element.\n * @param [props]\n * @param [props.label] Input label.\n * @param [props.theme] _Ad hoc_ theme.\n * @param [props...] [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)\n * @param [props...] Any other properties are passed to the underlying\n * `<input>` element.\n */\nconst Input = forwardRef<HTMLInputElement, PropsT>((\n {\n label,\n theme,\n ...rest\n }: PropsT,\n ref,\n) => (\n <span className={theme.container}>\n { label === undefined ? null : <div className={theme.label}>{label}</div> }\n <input\n className={theme.input}\n ref={ref}\n {...rest} // eslint-disable-line react/jsx-props-no-spreading\n />\n </span>\n));\n\nexport default themed(Input, 'Input', defaultTheme);\n"],"mappings":";;;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEA,IAAAC,YAAA,GAAAC,sBAAA,CAAAF,OAAA;AAA8D,IAAAG,WAAA,GAAAH,OAAA;AAAA,MAAAI,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;
|
|
1
|
+
{"version":3,"file":"index.js","names":["_react","require","_reactThemes","_interopRequireDefault","_jsxRuntime","defaultTheme","Input","forwardRef","label","testId","theme","rest","ref","jsxs","className","container","children","undefined","jsx","input","_default","exports","default","themed"],"sources":["../../../../../src/shared/components/Input/index.tsx"],"sourcesContent":["import { forwardRef } from 'react';\n\nimport themed, { type Theme } from '@dr.pogodin/react-themes';\n\nimport defaultTheme from './theme.scss';\n\ntype ThemeKeyT =\n | 'container'\n | 'input'\n | 'label';\n\ntype PropsT = React.InputHTMLAttributes<HTMLInputElement> & {\n label?: React.ReactNode;\n testId?: string;\n theme: Theme<ThemeKeyT>;\n};\n\n/**\n * Themeable input field, based on the standard HTML `<input>` element.\n * @param [props]\n * @param [props.label] Input label.\n * @param [props.theme] _Ad hoc_ theme.\n * @param [props...] [Other theming properties](https://www.npmjs.com/package/@dr.pogodin/react-themes#themed-component-properties)\n * @param [props...] Any other properties are passed to the underlying\n * `<input>` element.\n */\nconst Input = forwardRef<HTMLInputElement, PropsT>((\n {\n label,\n testId,\n theme,\n ...rest\n }: PropsT,\n ref,\n) => (\n <span className={theme.container}>\n { label === undefined ? null : <div className={theme.label}>{label}</div> }\n <input\n className={theme.input}\n data-testid={testId}\n ref={ref}\n {...rest} // eslint-disable-line react/jsx-props-no-spreading\n />\n </span>\n));\n\nexport default themed(Input, 'Input', defaultTheme);\n"],"mappings":";;;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEA,IAAAC,YAAA,GAAAC,sBAAA,CAAAF,OAAA;AAA8D,IAAAG,WAAA,GAAAH,OAAA;AAAA,MAAAI,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAe9D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,KAAK,gBAAG,IAAAC,iBAAU,EAA2B,CACjD;EACEC,KAAK;EACLC,MAAM;EACNC,KAAK;EACL,GAAGC;AACG,CAAC,EACTC,GAAG,kBAEH,IAAAR,WAAA,CAAAS,IAAA;EAAMC,SAAS,EAAEJ,KAAK,CAACK,SAAU;EAAAC,QAAA,GAC7BR,KAAK,KAAKS,SAAS,GAAG,IAAI,gBAAG,IAAAb,WAAA,CAAAc,GAAA;IAAKJ,SAAS,EAAEJ,KAAK,CAACF,KAAM;IAAAQ,QAAA,EAAER;EAAK,CAAM,CAAC,eACzE,IAAAJ,WAAA,CAAAc,GAAA;IACEJ,SAAS,EAAEJ,KAAK,CAACS,KAAM;IACvB,eAAaV,MAAO;IACpBG,GAAG,EAAEA,GAAI;IAAA,GACLD;EAAI,CACT,CAAC;AAAA,CACE,CACP,CAAC;AAAC,IAAAS,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAEY,IAAAC,oBAAM,EAACjB,KAAK,EAAE,OAAO,EAAED,YAAY,CAAC","ignoreList":[]}
|
|
@@ -37,6 +37,8 @@ const BaseModal = ({
|
|
|
37
37
|
containerStyle,
|
|
38
38
|
dontDisableScrolling,
|
|
39
39
|
onCancel,
|
|
40
|
+
style,
|
|
41
|
+
testId,
|
|
40
42
|
theme
|
|
41
43
|
}) => {
|
|
42
44
|
const containerRef = (0, _react.useRef)(null);
|
|
@@ -116,11 +118,12 @@ const BaseModal = ({
|
|
|
116
118
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
117
119
|
"aria-modal": "true",
|
|
118
120
|
className: theme.container,
|
|
121
|
+
"data-testid": testId,
|
|
119
122
|
onClick: e => e.stopPropagation(),
|
|
120
123
|
onWheel: event => event.stopPropagation(),
|
|
121
124
|
ref: containerRef,
|
|
122
125
|
role: "dialog",
|
|
123
|
-
style: containerStyle,
|
|
126
|
+
style: style ?? containerStyle,
|
|
124
127
|
children: children
|
|
125
128
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
126
129
|
onFocus: () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_react","require","_reactDom","_interopRequireDefault","_reactThemes","_jsxRuntime","baseTheme","S","BaseModal","cancelOnScrolling","children","containerStyle","dontDisableScrolling","onCancel","theme","containerRef","useRef","overlayRef","portal","setPortal","useState","useEffect","p","document","createElement","body","appendChild","removeChild","window","addEventListener","removeEventListener","classList","add","scrollingDisabledByModal","remove","focusLast","useMemo","jsx","onFocus","elems","current","querySelectorAll","i","length","focus","activeElement","tabIndex","ReactDom","createPortal","jsxs","Fragment","className","overlay","onClick","e","stopPropagation","onKeyDown","key","ref","node","role","container","onWheel","event","style","exports","_default","default","themed"],"sources":["../../../../../src/shared/components/Modal/index.tsx"],"sourcesContent":["/* global document */\n\nimport {\n type ReactNode,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport ReactDom 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 containerStyle?: React.CSSProperties;\n dontDisableScrolling?: boolean;\n onCancel?: () => void;\n theme: Theme<'container' | 'overlay'>;\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: React.FunctionComponent<PropsT> = ({\n cancelOnScrolling,\n children,\n containerStyle,\n dontDisableScrolling,\n onCancel,\n theme,\n}) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const [portal, setPortal] = useState<HTMLDivElement>();\n\n useEffect(() => {\n const p = document.createElement('div');\n document.body.appendChild(p);\n setPortal(p);\n return () => {\n document.body.removeChild(p);\n };\n }, []);\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('*') as NodeListOf<HTMLElement>;\n for (let i = elems.length - 1; i >= 0; --i) {\n elems[i]?.focus();\n if (document.activeElement === elems[i]) return;\n }\n overlayRef.current?.focus();\n }}\n /* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n tabIndex={0}\n /* eslint-enable jsx-a11y/no-noninteractive-tabindex */\n />\n ), []);\n\n return portal ? ReactDom.createPortal(\n (\n <>\n {focusLast}\n <div\n aria-label=\"Cancel\"\n className={theme.overlay}\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 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 /* eslint-disable jsx-a11y/click-events-have-key-events,\n jsx-a11y/no-noninteractive-element-interactions */\n }\n <div\n aria-modal=\"true\"\n className={theme.container}\n onClick={(e) => e.stopPropagation()}\n onWheel={(event) => event.stopPropagation()}\n ref={containerRef}\n role=\"dialog\"\n style={containerStyle}\n >\n {children}\n </div>\n {/* eslint-enable jsx-a11y/click-events-have-key-events,\n jsx-a11y/no-noninteractive-element-interactions */}\n <div\n onFocus={() => {\n overlayRef.current?.focus();\n }}\n /* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n tabIndex={0}\n /* eslint-enable jsx-a11y/no-noninteractive-tabindex */\n />\n {focusLast}\n </>\n ),\n portal,\n ) : null;\n};\n\nexport default themed(BaseModal, 'Modal', baseTheme);\n\n/* Non-themed version of the Modal. */\nexport { BaseModal };\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"index.js","names":["_react","require","_reactDom","_interopRequireDefault","_reactThemes","_jsxRuntime","baseTheme","S","BaseModal","cancelOnScrolling","children","containerStyle","dontDisableScrolling","onCancel","style","testId","theme","containerRef","useRef","overlayRef","portal","setPortal","useState","useEffect","p","document","createElement","body","appendChild","removeChild","window","addEventListener","removeEventListener","classList","add","scrollingDisabledByModal","remove","focusLast","useMemo","jsx","onFocus","elems","current","querySelectorAll","i","length","focus","activeElement","tabIndex","ReactDom","createPortal","jsxs","Fragment","className","overlay","onClick","e","stopPropagation","onKeyDown","key","ref","node","role","container","onWheel","event","exports","_default","default","themed"],"sources":["../../../../../src/shared/components/Modal/index.tsx"],"sourcesContent":["/* global document */\n\nimport {\n type ReactNode,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport ReactDom 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 style?: React.CSSProperties;\n testId?: string;\n theme: Theme<'container' | 'overlay'>;\n\n /** @deprecated */\n containerStyle?: React.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: React.FunctionComponent<PropsT> = ({\n cancelOnScrolling,\n children,\n containerStyle,\n dontDisableScrolling,\n onCancel,\n style,\n testId,\n theme,\n}) => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const [portal, setPortal] = useState<HTMLDivElement>();\n\n useEffect(() => {\n const p = document.createElement('div');\n document.body.appendChild(p);\n setPortal(p);\n return () => {\n document.body.removeChild(p);\n };\n }, []);\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('*') as NodeListOf<HTMLElement>;\n for (let i = elems.length - 1; i >= 0; --i) {\n elems[i]?.focus();\n if (document.activeElement === elems[i]) return;\n }\n overlayRef.current?.focus();\n }}\n /* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n tabIndex={0}\n /* eslint-enable jsx-a11y/no-noninteractive-tabindex */\n />\n ), []);\n\n return portal ? ReactDom.createPortal(\n (\n <>\n {focusLast}\n <div\n aria-label=\"Cancel\"\n className={theme.overlay}\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 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 /* eslint-disable jsx-a11y/click-events-have-key-events,\n jsx-a11y/no-noninteractive-element-interactions */\n }\n <div\n aria-modal=\"true\"\n className={theme.container}\n data-testid={testId}\n onClick={(e) => e.stopPropagation()}\n onWheel={(event) => event.stopPropagation()}\n ref={containerRef}\n role=\"dialog\"\n style={style ?? containerStyle}\n >\n {children}\n </div>\n {/* eslint-enable jsx-a11y/click-events-have-key-events,\n jsx-a11y/no-noninteractive-element-interactions */}\n <div\n onFocus={() => {\n overlayRef.current?.focus();\n }}\n /* eslint-disable jsx-a11y/no-noninteractive-tabindex */\n tabIndex={0}\n /* eslint-enable jsx-a11y/no-noninteractive-tabindex */\n />\n {focusLast}\n </>\n ),\n portal,\n ) : null;\n};\n\nexport default themed(BaseModal, 'Modal', baseTheme);\n\n/* Non-themed version of the Modal. */\nexport { BaseModal };\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -47,6 +47,7 @@ const Dropdown = ({
|
|
|
47
47
|
label,
|
|
48
48
|
onChange,
|
|
49
49
|
options,
|
|
50
|
+
testId,
|
|
50
51
|
theme,
|
|
51
52
|
value
|
|
52
53
|
}) => {
|
|
@@ -87,6 +88,7 @@ const Dropdown = ({
|
|
|
87
88
|
className: theme.dropdown,
|
|
88
89
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("select", {
|
|
89
90
|
className: selectClassName,
|
|
91
|
+
"data-testid": testId,
|
|
90
92
|
onChange: onChange,
|
|
91
93
|
value: value,
|
|
92
94
|
children: [hiddenOption, optionElements]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_reactThemes","_interopRequireDefault","require","_common","_jsxRuntime","defaultTheme","Dropdown","filter","label","onChange","options","theme","value","Error","isValidValue","optionElements","i","length","option","undefined","iValue","iName","optionValueName","push","jsx","className","children","hiddenOption","disabled","selectClassName","select","invalid","jsxs","container","dropdown","arrow","_default","exports","default","themed"],"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 defaultTheme from './theme.scss';\n\nimport { type PropsT, optionValueName } from '../common';\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 theme,\n value,\n}) => {\n if (!options) throw Error('Internal error');\n\n let isValidValue = false;\n const optionElements = [];\n\n for (let i = 0; i < options.length; ++i) {\n const option = options[i];\n if (option !== undefined && (!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 disabled\n className={theme.hiddenOption}\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 ? null : <div className={theme.label}>{label}</div> }\n <div className={theme.dropdown}>\n <select\n className={selectClassName}\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 themed(Dropdown, 'Dropdown', defaultTheme);\n"],"mappings":";;;;;;;AAEA,IAAAA,YAAA,GAAAC,sBAAA,CAAAC,OAAA;AAIA,IAAAC,OAAA,GAAAD,OAAA;AAAyD,IAAAE,WAAA,GAAAF,OAAA;AANzD;AAAA,MAAAG,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,QAAiD,GAAGA,CAAC;EACzDC,MAAM;EACNC,KAAK;EACLC,QAAQ;EACRC,OAAO;EACPC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,IAAI,
|
|
1
|
+
{"version":3,"file":"index.js","names":["_reactThemes","_interopRequireDefault","require","_common","_jsxRuntime","defaultTheme","Dropdown","filter","label","onChange","options","testId","theme","value","Error","isValidValue","optionElements","i","length","option","undefined","iValue","iName","optionValueName","push","jsx","className","children","hiddenOption","disabled","selectClassName","select","invalid","jsxs","container","dropdown","arrow","_default","exports","default","themed"],"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 defaultTheme from './theme.scss';\n\nimport { type PropsT, optionValueName } from '../common';\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 if (!options) throw Error('Internal error');\n\n let isValidValue = false;\n const optionElements = [];\n\n for (let i = 0; i < options.length; ++i) {\n const option = options[i];\n if (option !== undefined && (!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 disabled\n className={theme.hiddenOption}\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 ? null : <div className={theme.label}>{label}</div> }\n <div className={theme.dropdown}>\n <select\n className={selectClassName}\n data-testid={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 themed(Dropdown, 'Dropdown', defaultTheme);\n"],"mappings":";;;;;;;AAEA,IAAAA,YAAA,GAAAC,sBAAA,CAAAC,OAAA;AAIA,IAAAC,OAAA,GAAAD,OAAA;AAAyD,IAAAE,WAAA,GAAAF,OAAA;AANzD;AAAA,MAAAG,YAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;AAAA;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,QAAiD,GAAGA,CAAC;EACzDC,MAAM;EACNC,KAAK;EACLC,QAAQ;EACRC,OAAO;EACPC,MAAM;EACNC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,IAAI,CAACH,OAAO,EAAE,MAAMI,KAAK,CAAC,gBAAgB,CAAC;EAE3C,IAAIC,YAAY,GAAG,KAAK;EACxB,MAAMC,cAAc,GAAG,EAAE;EAEzB,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGP,OAAO,CAACQ,MAAM,EAAE,EAAED,CAAC,EAAE;IACvC,MAAME,MAAM,GAAGT,OAAO,CAACO,CAAC,CAAC;IACzB,IAAIE,MAAM,KAAKC,SAAS,KAAK,CAACb,MAAM,IAAIA,MAAM,CAACY,MAAM,CAAC,CAAC,EAAE;MACvD,MAAM,CAACE,MAAM,EAAEC,KAAK,CAAC,GAAG,IAAAC,uBAAe,EAACJ,MAAM,CAAC;MAC/CJ,YAAY,KAAKM,MAAM,KAAKR,KAAK;MACjCG,cAAc,CAACQ,IAAI,eACjB,IAAApB,WAAA,CAAAqB,GAAA;QAAQC,SAAS,EAAEd,KAAK,CAACO,MAAO;QAAcN,KAAK,EAAEQ,MAAO;QAAAM,QAAA,EACzDL;MAAK,GAD8BD,MAE9B,CACV,CAAC;IACH;EACF;;EAEA;EACA;EACA;EACA;EACA,MAAMO,YAAY,GAAGb,YAAY,GAAG,IAAI,gBACtC,IAAAX,WAAA,CAAAqB,GAAA;IACEI,QAAQ;IACRH,SAAS,EAAEd,KAAK,CAACgB,YAAa;IAE9Bf,KAAK,EAAEA,KAAM;IAAAc,QAAA,EAEZd;EAAK,GAHF,0BAIE,CACT;EAED,IAAIiB,eAAe,GAAGlB,KAAK,CAACmB,MAAM;EAClC,IAAI,CAAChB,YAAY,EAAEe,eAAe,IAAI,IAAIlB,KAAK,CAACoB,OAAO,EAAE;EAEzD,oBACE,IAAA5B,WAAA,CAAA6B,IAAA;IAAKP,SAAS,EAAEd,KAAK,CAACsB,SAAU;IAAAP,QAAA,GAC5BnB,KAAK,KAAKY,SAAS,GAAG,IAAI,gBAAG,IAAAhB,WAAA,CAAAqB,GAAA;MAAKC,SAAS,EAAEd,KAAK,CAACJ,KAAM;MAAAmB,QAAA,EAAEnB;IAAK,CAAM,CAAC,eACzE,IAAAJ,WAAA,CAAA6B,IAAA;MAAKP,SAAS,EAAEd,KAAK,CAACuB,QAAS;MAAAR,QAAA,gBAC7B,IAAAvB,WAAA,CAAA6B,IAAA;QACEP,SAAS,EAAEI,eAAgB;QAC3B,eAAanB,MAAO;QACpBF,QAAQ,EAAEA,QAAS;QACnBI,KAAK,EAAEA,KAAM;QAAAc,QAAA,GAEZC,YAAY,EACZZ,cAAc;MAAA,CACT,CAAC,eACT,IAAAZ,WAAA,CAAAqB,GAAA;QAAKC,SAAS,EAAEd,KAAK,CAACwB;MAAM,CAAE,CAAC;IAAA,CAC5B,CAAC;EAAA,CACH,CAAC;AAEV,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAEa,IAAAC,oBAAM,EAAClC,QAAQ,EAAE,UAAU,EAAED,YAAY,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 =\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\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 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;;
|
|
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 =\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\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;;AA6CA,SAASA,OAAOA,CAAIC,CAAsB,EAAe;EACvD,MAAMC,IAAI,GAAG,OAAOD,CAAC;EACrB,OAAOC,IAAI,KAAK,QAAQ,IAAIA,IAAI,KAAK,QAAQ;AAC/C;;AAEA;AACO,SAASC,eAAeA,CAC7BC,MAA+B,EACL;EAC1B,OAAOJ,OAAO,CAACI,MAAM,CAAC,GAClB,CAACA,MAAM,EAAEA,MAAM,CAAC,GAChB,CAACA,MAAM,CAACC,KAAK,EAAED,MAAM,CAACE,IAAI,IAAIF,MAAM,CAACC,KAAK,CAAC;AACjD","ignoreList":[]}
|
|
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "getGlobal", {
|
|
|
17
17
|
}
|
|
18
18
|
});
|
|
19
19
|
exports.getMockUuid = getMockUuid;
|
|
20
|
+
exports.mockAxios = mockAxios;
|
|
20
21
|
exports.mockClientSide = mockClientSide;
|
|
21
22
|
exports.mockTimer = mockTimer;
|
|
22
23
|
exports.mount = mount;
|
|
@@ -68,6 +69,33 @@ function getMockUuid(seed = 0) {
|
|
|
68
69
|
const x = seed.toString(16).padStart(32, '0');
|
|
69
70
|
return `${x.slice(0, 8)}-${x.slice(8, 12)}-${x.slice(12, 16)}-${x.slice(16, 20)}-${x.slice(20)}`;
|
|
70
71
|
}
|
|
72
|
+
function mockAxios(handlers) {
|
|
73
|
+
const axios = jest.requireActual('axios');
|
|
74
|
+
axios.defaults.adapter = async config => {
|
|
75
|
+
for (let i = 0; i < handlers.length; ++i) {
|
|
76
|
+
const res = handlers[i]?.(config);
|
|
77
|
+
if (res) {
|
|
78
|
+
return {
|
|
79
|
+
config: config,
|
|
80
|
+
data: null,
|
|
81
|
+
headers: {},
|
|
82
|
+
status: 200,
|
|
83
|
+
statusText: 'OK',
|
|
84
|
+
...res
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Fallback to the regular network request.
|
|
90
|
+
const res = await axios({
|
|
91
|
+
...config,
|
|
92
|
+
adapter: ['xhr', 'http', 'fetch']
|
|
93
|
+
});
|
|
94
|
+
console.warn('Network request has not been mocked for a test.\n\nConfig:\n', config, '\n\nResult:\n', JSON.stringify(res, null, 2));
|
|
95
|
+
return res;
|
|
96
|
+
};
|
|
97
|
+
return axios;
|
|
98
|
+
}
|
|
71
99
|
|
|
72
100
|
/**
|
|
73
101
|
* Advances mock timers, and mock date by the specified time.
|
|
@@ -97,6 +125,9 @@ function mount(scene) {
|
|
|
97
125
|
(0, _react.act)(() => root.unmount());
|
|
98
126
|
res.remove();
|
|
99
127
|
};
|
|
128
|
+
res.snapshot = () => {
|
|
129
|
+
expect(res).toMatchSnapshot();
|
|
130
|
+
};
|
|
100
131
|
|
|
101
132
|
// NOTE: As it seems @testing-library may reset this flag to false
|
|
102
133
|
// when it is simulating user events.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_mockdate","_interopRequireDefault","require","_react","_client","_react2","_global","global","IS_REACT_ACT_ENVIRONMENT","originalProcessVersions","process","versions","mockClientSide","Object","defineProperty","value","unmockClientSide","writable","getMockUuid","seed","x","toString","padStart","slice","mockTimer","time","mockdate","set","Date","now","
|
|
1
|
+
{"version":3,"file":"index.js","names":["_mockdate","_interopRequireDefault","require","_react","_client","_react2","_global","global","IS_REACT_ACT_ENVIRONMENT","originalProcessVersions","process","versions","mockClientSide","Object","defineProperty","value","unmockClientSide","writable","getMockUuid","seed","x","toString","padStart","slice","mockAxios","handlers","axios","jest","requireActual","defaults","adapter","config","i","length","res","data","headers","status","statusText","console","warn","JSON","stringify","mockTimer","time","mockdate","set","Date","now","advanceTimersByTime","mount","scene","root","element","document","createElement","body","appendChild","destroy","act","unmount","remove","snapshot","expect","toMatchSnapshot","createRoot","render","options","promise","await","undefined","Error","nodes","asFragment","childNodes"],"sources":["../../../../../src/shared/utils/jest/index.tsx"],"sourcesContent":["/* global jest, document */\n/* eslint-disable import/no-extraneous-dependencies */\n\nimport type {\n AxiosRequestConfig,\n AxiosResponse,\n InternalAxiosRequestConfig,\n} from 'axios';\n\nimport mockdate from 'mockdate';\nimport { type ReactNode, act } from 'react';\nimport { type Root, createRoot } from 'react-dom/client';\n\nimport { type RenderResult, render } from '@testing-library/react';\n\n/**\n * An alias for [act(..)](https://reactjs.org/docs/test-utils.html#act)\n * from `react`.\n */\nexport { act };\n\nexport { default as getGlobal } from './global';\n\ndeclare global {\n // eslint-disable-next-line no-var, vars-on-top\n var IS_REACT_ACT_ENVIRONMENT: boolean | undefined;\n}\n\nglobal.IS_REACT_ACT_ENVIRONMENT = true;\n\nconst originalProcessVersions = process.versions;\n\n/**\n * Tricks **react-utils** into thinking the test is running within client-side\n * (browser) environment.\n */\nexport function mockClientSide() {\n Object.defineProperty(process, 'versions', { value: null });\n}\n\n/**\n * Reverts the effect of {@link module:JU.mockClientSide mockClientSide(..)}.\n */\nexport function unmockClientSide() {\n Object.defineProperty(process, 'versions', {\n value: originalProcessVersions,\n writable: false,\n });\n}\n\n/**\n * Generates a mock UUID, or better said it determenistically transforms given\n * `seed` number into a UUID-formatted string.\n * @param {number} seed\n * @return {string}\n */\nexport function getMockUuid(seed = 0) {\n const x = seed.toString(16).padStart(32, '0');\n return `${x.slice(0, 8)}-${x.slice(8, 12)}-${x.slice(12, 16)}-${x.slice(16, 20)}-${x.slice(20)}`;\n}\n\nexport type AxiosRequestHandlerT =\n (config: AxiosRequestConfig) => Partial<AxiosResponse> | null | undefined;\n\nexport function mockAxios(handlers: AxiosRequestHandlerT[]) {\n const axios = jest.requireActual('axios');\n\n axios.defaults.adapter = async (config: AxiosRequestConfig): Promise<AxiosResponse> => {\n for (let i = 0; i < handlers.length; ++i) {\n const res = handlers[i]?.(config);\n if (res) {\n return {\n config: config as InternalAxiosRequestConfig,\n data: null,\n headers: {},\n status: 200,\n statusText: 'OK',\n ...res,\n };\n }\n }\n\n // Fallback to the regular network request.\n const res = await axios({ ...config, adapter: ['xhr', 'http', 'fetch'] });\n\n console.warn(\n 'Network request has not been mocked for a test.\\n\\nConfig:\\n',\n config,\n '\\n\\nResult:\\n',\n JSON.stringify(res, null, 2),\n );\n\n return res;\n };\n\n return axios;\n}\n\n/**\n * Advances mock timers, and mock date by the specified time.\n * @param {number} time Time step [ms].\n * @returns {Promise} Wait for this to \"jump after\" any async code which should\n * be executed because of the mock time movement.\n */\nexport async function mockTimer(time: number) {\n mockdate.set(time + Date.now());\n jest.advanceTimersByTime(time);\n}\n\nexport type MountedSceneT = HTMLElement & {\n destroy: () => void;\n snapshot: () => void;\n};\n\n/**\n * Mounts `scene` to the DOM, and returns the root scene element.\n * @param scene\n * @return Created container DOM element with destroy() function\n * attached.\n */\nexport function mount(scene: ReactNode): MountedSceneT {\n let root: Root;\n const element = document.createElement('div');\n document.body.appendChild(element);\n\n const res: MountedSceneT = (element as unknown) as MountedSceneT;\n res.destroy = () => {\n // NOTE: As it seems @testing-library may reset this flag to false\n // when it is simulating user events.\n global.IS_REACT_ACT_ENVIRONMENT = true;\n\n act(() => root.unmount());\n res.remove();\n };\n\n res.snapshot = () => {\n expect(res).toMatchSnapshot();\n };\n\n // NOTE: As it seems @testing-library may reset this flag to false\n // when it is simulating user events.\n global.IS_REACT_ACT_ENVIRONMENT = true;\n\n act(() => {\n root = createRoot(res);\n root.render(scene);\n });\n return res;\n}\n\ntype SnapshotOptionsT = {\n await?: Promise<void>;\n};\n\nexport async function snapshot(\n element: React.ReactElement,\n options?: SnapshotOptionsT,\n) {\n let res: RenderResult | undefined;\n\n const promise = act(() => {\n res = render(element);\n return options?.await;\n });\n\n if (res === undefined) throw Error('Render failed');\n if (options?.await) await promise;\n\n const nodes = res.asFragment().childNodes;\n expect(nodes.length > 1 ? [...nodes] : nodes[0]).toMatchSnapshot();\n return res;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AASA,IAAAA,SAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,OAAA,GAAAF,OAAA;AAEA,IAAAG,OAAA,GAAAH,OAAA;AAQA,IAAAI,OAAA,GAAAL,sBAAA,CAAAC,OAAA;AArBA;AACA;;AAcA;AACA;AACA;AACA;;AAUAK,MAAM,CAACC,wBAAwB,GAAG,IAAI;AAEtC,MAAMC,uBAAuB,GAAGC,OAAO,CAACC,QAAQ;;AAEhD;AACA;AACA;AACA;AACO,SAASC,cAAcA,CAAA,EAAG;EAC/BC,MAAM,CAACC,cAAc,CAACJ,OAAO,EAAE,UAAU,EAAE;IAAEK,KAAK,EAAE;EAAK,CAAC,CAAC;AAC7D;;AAEA;AACA;AACA;AACO,SAASC,gBAAgBA,CAAA,EAAG;EACjCH,MAAM,CAACC,cAAc,CAACJ,OAAO,EAAE,UAAU,EAAE;IACzCK,KAAK,EAAEN,uBAAuB;IAC9BQ,QAAQ,EAAE;EACZ,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,WAAWA,CAACC,IAAI,GAAG,CAAC,EAAE;EACpC,MAAMC,CAAC,GAAGD,IAAI,CAACE,QAAQ,CAAC,EAAE,CAAC,CAACC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;EAC7C,OAAO,GAAGF,CAAC,CAACG,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAIH,CAAC,CAACG,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAIH,CAAC,CAACG,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAIH,CAAC,CAACG,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,IAAIH,CAAC,CAACG,KAAK,CAAC,EAAE,CAAC,EAAE;AAClG;AAKO,SAASC,SAASA,CAACC,QAAgC,EAAE;EAC1D,MAAMC,KAAK,GAAGC,IAAI,CAACC,aAAa,CAAC,OAAO,CAAC;EAEzCF,KAAK,CAACG,QAAQ,CAACC,OAAO,GAAG,MAAOC,MAA0B,IAA6B;IACrF,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGP,QAAQ,CAACQ,MAAM,EAAE,EAAED,CAAC,EAAE;MACxC,MAAME,GAAG,GAAGT,QAAQ,CAACO,CAAC,CAAC,GAAGD,MAAM,CAAC;MACjC,IAAIG,GAAG,EAAE;QACP,OAAO;UACLH,MAAM,EAAEA,MAAoC;UAC5CI,IAAI,EAAE,IAAI;UACVC,OAAO,EAAE,CAAC,CAAC;UACXC,MAAM,EAAE,GAAG;UACXC,UAAU,EAAE,IAAI;UAChB,GAAGJ;QACL,CAAC;MACH;IACF;;IAEA;IACA,MAAMA,GAAG,GAAG,MAAMR,KAAK,CAAC;MAAE,GAAGK,MAAM;MAAED,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO;IAAE,CAAC,CAAC;IAEzES,OAAO,CAACC,IAAI,CACV,8DAA8D,EAC9DT,MAAM,EACN,eAAe,EACfU,IAAI,CAACC,SAAS,CAACR,GAAG,EAAE,IAAI,EAAE,CAAC,CAC7B,CAAC;IAED,OAAOA,GAAG;EACZ,CAAC;EAED,OAAOR,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA;AACA;AACO,eAAeiB,SAASA,CAACC,IAAY,EAAE;EAC5CC,iBAAQ,CAACC,GAAG,CAACF,IAAI,GAAGG,IAAI,CAACC,GAAG,CAAC,CAAC,CAAC;EAC/BrB,IAAI,CAACsB,mBAAmB,CAACL,IAAI,CAAC;AAChC;AAOA;AACA;AACA;AACA;AACA;AACA;AACO,SAASM,KAAKA,CAACC,KAAgB,EAAiB;EACrD,IAAIC,IAAU;EACd,MAAMC,OAAO,GAAGC,QAAQ,CAACC,aAAa,CAAC,KAAK,CAAC;EAC7CD,QAAQ,CAACE,IAAI,CAACC,WAAW,CAACJ,OAAO,CAAC;EAElC,MAAMnB,GAAkB,GAAImB,OAAoC;EAChEnB,GAAG,CAACwB,OAAO,GAAG,MAAM;IAClB;IACA;IACAnD,MAAM,CAACC,wBAAwB,GAAG,IAAI;IAEtC,IAAAmD,UAAG,EAAC,MAAMP,IAAI,CAACQ,OAAO,CAAC,CAAC,CAAC;IACzB1B,GAAG,CAAC2B,MAAM,CAAC,CAAC;EACd,CAAC;EAED3B,GAAG,CAAC4B,QAAQ,GAAG,MAAM;IACnBC,MAAM,CAAC7B,GAAG,CAAC,CAAC8B,eAAe,CAAC,CAAC;EAC/B,CAAC;;EAED;EACA;EACAzD,MAAM,CAACC,wBAAwB,GAAG,IAAI;EAEtC,IAAAmD,UAAG,EAAC,MAAM;IACRP,IAAI,GAAG,IAAAa,kBAAU,EAAC/B,GAAG,CAAC;IACtBkB,IAAI,CAACc,MAAM,CAACf,KAAK,CAAC;EACpB,CAAC,CAAC;EACF,OAAOjB,GAAG;AACZ;AAMO,eAAe4B,QAAQA,CAC5BT,OAA2B,EAC3Bc,OAA0B,EAC1B;EACA,IAAIjC,GAA6B;EAEjC,MAAMkC,OAAO,GAAG,IAAAT,UAAG,EAAC,MAAM;IACxBzB,GAAG,GAAG,IAAAgC,cAAM,EAACb,OAAO,CAAC;IACrB,OAAOc,OAAO,EAAEE,KAAK;EACvB,CAAC,CAAC;EAEF,IAAInC,GAAG,KAAKoC,SAAS,EAAE,MAAMC,KAAK,CAAC,eAAe,CAAC;EACnD,IAAIJ,OAAO,EAAEE,KAAK,EAAE,MAAMD,OAAO;EAEjC,MAAMI,KAAK,GAAGtC,GAAG,CAACuC,UAAU,CAAC,CAAC,CAACC,UAAU;EACzCX,MAAM,CAACS,KAAK,CAACvC,MAAM,GAAG,CAAC,GAAG,CAAC,GAAGuC,KAAK,CAAC,GAAGA,KAAK,CAAC,CAAC,CAAC,CAAC,CAACR,eAAe,CAAC,CAAC;EAClE,OAAO9B,GAAG;AACZ","ignoreList":[]}
|
|
@@ -678,6 +678,14 @@ body {
|
|
|
678
678
|
/*!*************************************************************************************************************************************************************************************************************************************************************************************************************!*\
|
|
679
679
|
!*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[2].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[2].use[2]!./node_modules/resolve-url-loader/index.js!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[2].use[4]!./src/shared/components/Throbber/theme.scss ***!
|
|
680
680
|
\*************************************************************************************************************************************************************************************************************************************************************************************************************/
|
|
681
|
+
@keyframes -dr-pogodin-react-utils___src-shared-components-Throbber-theme___bouncing___TJe-6j {
|
|
682
|
+
from {
|
|
683
|
+
top: -0.3em;
|
|
684
|
+
}
|
|
685
|
+
to {
|
|
686
|
+
top: 0.3em;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
681
689
|
*.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___container___7zdld4,
|
|
682
690
|
.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___context___uIObt7.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___container___7zdld4,
|
|
683
691
|
.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___ad___XIxe9o.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___hoc___YOyORH.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___container___7zdld4 {
|
|
@@ -695,14 +703,6 @@ body {
|
|
|
695
703
|
position: relative;
|
|
696
704
|
width: 0.6em;
|
|
697
705
|
}
|
|
698
|
-
@keyframes -dr-pogodin-react-utils___src-shared-components-Throbber-theme___bouncing___TJe-6j {
|
|
699
|
-
from {
|
|
700
|
-
top: -0.3em;
|
|
701
|
-
}
|
|
702
|
-
to {
|
|
703
|
-
top: 0.3em;
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
706
|
*.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___circle___dBrB4g:first-child,
|
|
707
707
|
.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___context___uIObt7.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___circle___dBrB4g:first-child,
|
|
708
708
|
.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___ad___XIxe9o.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___hoc___YOyORH.-dr-pogodin-react-utils___src-shared-components-Throbber-theme___circle___dBrB4g:first-child {
|