@vkontakte/vkui 5.6.0 → 5.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/AppRoot/AppRoot.js +4 -2
- package/dist/cjs/components/AppRoot/AppRoot.js.map +1 -1
- package/dist/cjs/components/FormItem/FormItem.d.ts +7 -1
- package/dist/cjs/components/FormItem/FormItem.js +6 -3
- package/dist/cjs/components/FormItem/FormItem.js.map +1 -1
- package/dist/cjs/components/Search/Search.js +1 -3
- package/dist/cjs/components/Search/Search.js.map +1 -1
- package/dist/cjs/components/SubnavigationBar/SubnavigationBar.js +13 -3
- package/dist/cjs/components/SubnavigationBar/SubnavigationBar.js.map +1 -1
- package/dist/cjs/helpers/math.js +19 -8
- package/dist/cjs/helpers/math.js.map +1 -1
- package/dist/components/AppRoot/AppRoot.js +4 -2
- package/dist/components/AppRoot/AppRoot.js.map +1 -1
- package/dist/components/FormItem/FormItem.d.ts +7 -1
- package/dist/components/FormItem/FormItem.js +6 -3
- package/dist/components/FormItem/FormItem.js.map +1 -1
- package/dist/components/Search/Search.js +1 -3
- package/dist/components/Search/Search.js.map +1 -1
- package/dist/components/SubnavigationBar/SubnavigationBar.js +13 -3
- package/dist/components/SubnavigationBar/SubnavigationBar.js.map +1 -1
- package/dist/components.css +4 -4
- package/dist/components.css.map +1 -1
- package/dist/components.js.tmp +43 -19
- package/dist/cssm/components/AppRoot/AppRoot.js +3 -1
- package/dist/cssm/components/AppRoot/AppRoot.js.map +1 -1
- package/dist/cssm/components/FormItem/FormItem.d.ts +7 -1
- package/dist/cssm/components/FormItem/FormItem.js +4 -2
- package/dist/cssm/components/FormItem/FormItem.js.map +1 -1
- package/dist/cssm/components/Search/Search.js +1 -3
- package/dist/cssm/components/Search/Search.js.map +1 -1
- package/dist/cssm/components/Search/Search.module.css +3 -0
- package/dist/cssm/components/SubnavigationBar/SubnavigationBar.js +11 -3
- package/dist/cssm/components/SubnavigationBar/SubnavigationBar.js.map +1 -1
- package/dist/cssm/components/SubnavigationBar/SubnavigationBar.module.css +21 -2
- package/dist/cssm/components/SubnavigationButton/SubnavigationButton.module.css +0 -9
- package/dist/cssm/components/Switch/Switch.module.css +4 -0
- package/dist/cssm/helpers/math.js +19 -8
- package/dist/cssm/helpers/math.js.map +1 -1
- package/dist/helpers/math.js +19 -8
- package/dist/helpers/math.js.map +1 -1
- package/dist/vkui.css +4 -4
- package/dist/vkui.css.map +1 -1
- package/dist/vkui.js.tmp +43 -19
- package/package.json +1 -1
package/dist/components.js.tmp
CHANGED
|
@@ -207,8 +207,10 @@ var INSET_CUSTOM_PROPERTY_PREFIX = "--vkui_internal--safe_area_inset_";
|
|
|
207
207
|
}
|
|
208
208
|
setPortalRoot(portal);
|
|
209
209
|
return function() {
|
|
210
|
-
|
|
211
|
-
|
|
210
|
+
if (!portalRootProp) {
|
|
211
|
+
var _portal_parentElement, _portal;
|
|
212
|
+
(_portal = portal) === null || _portal === void 0 ? void 0 : (_portal_parentElement = _portal.parentElement) === null || _portal_parentElement === void 0 ? void 0 : _portal_parentElement.removeChild(portal);
|
|
213
|
+
}
|
|
212
214
|
};
|
|
213
215
|
}, [
|
|
214
216
|
portalRootProp
|
|
@@ -8916,19 +8918,30 @@ function precisionRound(number) {
|
|
|
8916
8918
|
var factor = Math.pow(10, precision);
|
|
8917
8919
|
return Math.round(number * factor) / factor;
|
|
8918
8920
|
}
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
+
/**
|
|
8922
|
+
* Решение скопировано без изменений у MUI:
|
|
8923
|
+
* https://github.com/mui/material-ui/blob/v5.13.7/packages/mui-base/src/useSlider/useSlider.ts#L89-L105
|
|
8924
|
+
*/ function getDecimalPrecision(num) {
|
|
8925
|
+
// This handles the case when num is very small (0.00000001), js will turn this into 1e-8.
|
|
8926
|
+
// When num is bigger than 1 or less than -1 it won't get converted to this notation so it's fine.
|
|
8927
|
+
if (Math.abs(num) < 1) {
|
|
8928
|
+
var parts = num.toExponential().split("e-");
|
|
8929
|
+
var matissaDecimalPart = parts[0].split(".")[1];
|
|
8930
|
+
return (matissaDecimalPart ? matissaDecimalPart.length : 0) + parseInt(parts[1], 10);
|
|
8931
|
+
}
|
|
8932
|
+
var decimalPart = num.toString().split(".")[1];
|
|
8933
|
+
return decimalPart ? decimalPart.length : 0;
|
|
8934
|
+
}
|
|
8935
|
+
function roundValueToStep(value, step, min) {
|
|
8936
|
+
var nearest = Math.round((value - min) / step) * step + min;
|
|
8937
|
+
return Number(nearest.toFixed(getDecimalPrecision(step)));
|
|
8921
8938
|
}
|
|
8922
8939
|
function decimatedClamp(val, min, max, step) {
|
|
8923
8940
|
if (step == null || step <= 0) {
|
|
8924
8941
|
return clamp(val, min, max);
|
|
8925
8942
|
}
|
|
8926
|
-
var
|
|
8927
|
-
|
|
8928
|
-
var decimatedOffset = precisionRound(Math.round((val - min) / step) * step, prec);
|
|
8929
|
-
// Round range length _down_ to nearest min + k2 * step
|
|
8930
|
-
var decimatedRange = precisionRound(Math.floor((max - min) / step) * step, prec);
|
|
8931
|
-
return min + clamp(decimatedOffset, 0, decimatedRange);
|
|
8943
|
+
var roundedValue = roundValueToStep(val, step, min);
|
|
8944
|
+
return clamp(roundedValue, min, max);
|
|
8932
8945
|
}
|
|
8933
8946
|
function rescale(value, from, to) {
|
|
8934
8947
|
var options = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : {};
|
|
@@ -58334,10 +58347,8 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
58334
58347
|
var _inputRef_current;
|
|
58335
58348
|
e.originalEvent.preventDefault();
|
|
58336
58349
|
(_inputRef_current = inputRef.current) === null || _inputRef_current === void 0 ? void 0 : _inputRef_current.focus();
|
|
58337
|
-
onCancel();
|
|
58338
58350
|
}, [
|
|
58339
|
-
inputRef
|
|
58340
|
-
onCancel
|
|
58351
|
+
inputRef
|
|
58341
58352
|
]);
|
|
58342
58353
|
return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.createElement("div", {
|
|
58343
58354
|
className: (0,_vkontakte_vkjs__WEBPACK_IMPORTED_MODULE_1__.classNames)("vkuiInternalSearch", "vkuiSearch", sizeY === "none" && "vkuiSearch--sizeY-none", sizeY === _lib_adaptivity__WEBPACK_IMPORTED_MODULE_9__.SizeType.COMPACT && "vkuiSearch--sizeY-compact", isFocused && "vkuiSearch--focused", value && "vkuiSearch--has-value", after && "vkuiSearch--has-after", icon && "vkuiSearch--has-icon", className),
|
|
@@ -61501,12 +61512,22 @@ var defaultScrollToRight = function(x) {
|
|
|
61501
61512
|
};
|
|
61502
61513
|
}
|
|
61503
61514
|
return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.createElement("div", _object_spread_props(_object_spread({}, restProps), {
|
|
61504
|
-
className: (0,_vkontakte_vkjs__WEBPACK_IMPORTED_MODULE_1__.classNames)(
|
|
61515
|
+
className: (0,_vkontakte_vkjs__WEBPACK_IMPORTED_MODULE_1__.classNames)(// TODO: [>=6]
|
|
61516
|
+
// Заменить у SubnavigationButton `display: inline-block` на `width: 100%`
|
|
61517
|
+
// и удалить применение селектора в `SubnavigationButton.module.css`.
|
|
61518
|
+
// 2. Заменить глобальный селектор на CSS Modules `styles['SubnavigationBar--mode-fixed']`
|
|
61519
|
+
// mode !== 'fixed' && classNames('vkuiInternalSubnavigationBar--mode-fixed')
|
|
61520
|
+
mode === "fixed" && (0,_vkontakte_vkjs__WEBPACK_IMPORTED_MODULE_1__.classNames)("vkuiInternalSubnavigationBar--mode-fixed"), className)
|
|
61505
61521
|
}), /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.createElement(ScrollWrapper, _object_spread({
|
|
61506
61522
|
className: "vkuiSubnavigationBar__in"
|
|
61507
|
-
}, scrollWrapperProps), /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.createElement("
|
|
61523
|
+
}, scrollWrapperProps), /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.createElement("ul", {
|
|
61508
61524
|
className: "vkuiSubnavigationBar__scrollIn"
|
|
61509
|
-
}, children)
|
|
61525
|
+
}, react__WEBPACK_IMPORTED_MODULE_0__.Children.map(children, function(child, idx) {
|
|
61526
|
+
return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.createElement("li", {
|
|
61527
|
+
key: idx,
|
|
61528
|
+
className: "vkuiSubnavigationBar__item"
|
|
61529
|
+
}, child);
|
|
61530
|
+
}))));
|
|
61510
61531
|
};
|
|
61511
61532
|
|
|
61512
61533
|
|
|
@@ -62523,7 +62544,7 @@ var sizeYClassNames = _define_property({
|
|
|
62523
62544
|
/**
|
|
62524
62545
|
* @see https://vkcom.github.io/VKUI/#/FormItem
|
|
62525
62546
|
*/ var FormItem = function(_param) {
|
|
62526
|
-
var children = _param.children, top = _param.top, bottom = _param.bottom, _param_status = _param.status, status = _param_status === void 0 ? "default" : _param_status, _param_Component = _param.Component, Component = _param_Component === void 0 ? "div" : _param_Component, removable = _param.removable, _param_onRemove = _param.onRemove, onRemove = _param_onRemove === void 0 ? _vkontakte_vkjs__WEBPACK_IMPORTED_MODULE_1__.noop : _param_onRemove, _param_removePlaceholder = _param.removePlaceholder, removePlaceholder = _param_removePlaceholder === void 0 ? "Удалить" : _param_removePlaceholder, getRootRef = _param.getRootRef, className = _param.className, htmlFor = _param.htmlFor, restProps = _object_without_properties(_param, [
|
|
62547
|
+
var children = _param.children, top = _param.top, bottom = _param.bottom, _param_status = _param.status, status = _param_status === void 0 ? "default" : _param_status, _param_Component = _param.Component, Component = _param_Component === void 0 ? "div" : _param_Component, removable = _param.removable, _param_onRemove = _param.onRemove, onRemove = _param_onRemove === void 0 ? _vkontakte_vkjs__WEBPACK_IMPORTED_MODULE_1__.noop : _param_onRemove, _param_removePlaceholder = _param.removePlaceholder, removePlaceholder = _param_removePlaceholder === void 0 ? "Удалить" : _param_removePlaceholder, getRootRef = _param.getRootRef, className = _param.className, htmlFor = _param.htmlFor, bottomId = _param.bottomId, restProps = _object_without_properties(_param, [
|
|
62527
62548
|
"children",
|
|
62528
62549
|
"top",
|
|
62529
62550
|
"bottom",
|
|
@@ -62534,7 +62555,8 @@ var sizeYClassNames = _define_property({
|
|
|
62534
62555
|
"removePlaceholder",
|
|
62535
62556
|
"getRootRef",
|
|
62536
62557
|
"className",
|
|
62537
|
-
"htmlFor"
|
|
62558
|
+
"htmlFor",
|
|
62559
|
+
"bottomId"
|
|
62538
62560
|
]);
|
|
62539
62561
|
var rootEl = (0,_hooks_useExternRef__WEBPACK_IMPORTED_MODULE_4__.useExternRef)(getRootRef);
|
|
62540
62562
|
var _useAdaptivity = (0,_hooks_useAdaptivity__WEBPACK_IMPORTED_MODULE_5__.useAdaptivity)(), _useAdaptivity_sizeY = _useAdaptivity.sizeY, sizeY = _useAdaptivity_sizeY === void 0 ? "none" : _useAdaptivity_sizeY;
|
|
@@ -62543,7 +62565,9 @@ var sizeYClassNames = _define_property({
|
|
|
62543
62565
|
Component: htmlFor ? "label" : "h5",
|
|
62544
62566
|
htmlFor: htmlFor
|
|
62545
62567
|
}, top), children, (0,_vkontakte_vkjs__WEBPACK_IMPORTED_MODULE_1__.hasReactNode)(bottom) && /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.createElement(_Typography_Footnote_Footnote__WEBPACK_IMPORTED_MODULE_7__.Footnote, {
|
|
62546
|
-
className: "vkuiFormItem__bottom"
|
|
62568
|
+
className: "vkuiFormItem__bottom",
|
|
62569
|
+
id: bottomId,
|
|
62570
|
+
role: status === "error" ? "alert" : undefined
|
|
62547
62571
|
}, bottom));
|
|
62548
62572
|
return /*#__PURE__*/ react__WEBPACK_IMPORTED_MODULE_0__.createElement(Component, _object_spread_props(_object_spread({}, restProps), {
|
|
62549
62573
|
ref: rootEl,
|
|
@@ -43,7 +43,9 @@ const INSET_CUSTOM_PROPERTY_PREFIX = `--vkui_internal--safe_area_inset_`;
|
|
|
43
43
|
}
|
|
44
44
|
setPortalRoot(portal);
|
|
45
45
|
return ()=>{
|
|
46
|
-
|
|
46
|
+
if (!portalRootProp) {
|
|
47
|
+
portal?.parentElement?.removeChild(portal);
|
|
48
|
+
}
|
|
47
49
|
};
|
|
48
50
|
}, [
|
|
49
51
|
portalRootProp
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/AppRoot/AppRoot.tsx"],"sourcesContent":["import * as React from 'react';\nimport { IconSettingsProvider } from '@vkontakte/icons';\nimport { Insets } from '@vkontakte/vk-bridge';\nimport { classNames, noop } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useAppearance } from '../../hooks/useAppearance';\nimport { useInsets } from '../../hooks/useInsets';\nimport { useKeyboardInputTracker } from '../../hooks/useKeyboardInputTracker';\nimport { SizeType } from '../../lib/adaptivity';\nimport { useDOM } from '../../lib/dom';\nimport { isRefObject } from '../../lib/isRefObject';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport { AppRootContext } from './AppRootContext';\nimport { ElementScrollController, GlobalScrollController } from './ScrollContext';\nimport styles from './AppRoot.module.css';\n\nconst vkuiSizeXClassNames = {\n none: 'vkui--sizeX-none',\n [SizeType.REGULAR]: 'vkui--sizeX-regular',\n};\n\nconst INSET_CUSTOM_PROPERTY_PREFIX = `--vkui_internal--safe_area_inset_`;\n\n// Используйте classList, но будьте осторожны\n/* eslint-disable no-restricted-properties */\n\nexport interface AppRootProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Режим встраивания */\n mode?: 'partial' | 'embedded' | 'full';\n window?: Window;\n scroll?: 'global' | 'contain';\n /**\n * Кастомный root-элемент портала\n */\n portalRoot?: HTMLElement | React.RefObject<HTMLElement> | null;\n /** Disable portal for components */\n disablePortal?: boolean;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/AppRoot\n */\nexport const AppRoot = ({\n children,\n mode = 'full',\n scroll = 'global',\n portalRoot: portalRootProp = null,\n disablePortal,\n className,\n ...props\n}: AppRootProps) => {\n const isKeyboardInputActive = useKeyboardInputTracker();\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const [portalRoot, setPortalRoot] = React.useState<HTMLElement | null>(null);\n const { document } = useDOM();\n const insets = useInsets();\n const appearance = useAppearance();\n\n const { hasPointer, sizeX = 'none' } = useAdaptivity();\n\n // setup portal\n useIsomorphicLayoutEffect(() => {\n let portal: HTMLElement | null = null;\n if (portalRootProp) {\n if (isRefObject(portalRootProp)) {\n portal = portalRootProp.current;\n } else {\n portal = portalRootProp;\n }\n }\n if (!portal) {\n portal = document!.createElement('div');\n document!.body.appendChild(portal);\n }\n setPortalRoot(portal);\n return () => {\n portal?.parentElement?.removeChild(portal);\n };\n }, [portalRootProp]);\n\n // setup root classes\n useIsomorphicLayoutEffect(() => {\n if (mode === 'partial') {\n return noop;\n }\n\n const parent = rootRef.current?.parentElement;\n const classes = ['vkui__root'].concat(mode === 'embedded' ? 'vkui__root--embedded' : []);\n parent?.classList.add(...classes);\n\n return () => {\n parent?.classList.remove(...classes);\n };\n }, []);\n\n useIsomorphicLayoutEffect(() => {\n if (mode === 'full') {\n document!.documentElement.classList.add('vkui');\n\n return () => {\n document!.documentElement.classList.remove('vkui');\n };\n }\n\n return undefined;\n }, [document, mode]);\n\n // setup insets\n useIsomorphicLayoutEffect(() => {\n if (mode === 'partial' || !rootRef.current?.parentElement) {\n return noop;\n }\n\n const parent = rootRef.current.parentElement;\n\n let key: keyof Insets;\n for (key in insets) {\n if (insets.hasOwnProperty(key) && typeof insets[key] === 'number') {\n const inset = insets[key];\n parent.style.setProperty(INSET_CUSTOM_PROPERTY_PREFIX + key, `${inset}px`);\n portalRoot &&\n portalRoot.style.setProperty(INSET_CUSTOM_PROPERTY_PREFIX + key, `${inset}px`);\n }\n }\n\n return () => {\n let key: keyof Insets;\n for (key in insets) {\n if (insets.hasOwnProperty(key)) {\n parent.style.removeProperty(INSET_CUSTOM_PROPERTY_PREFIX + key);\n portalRoot && portalRoot.style.removeProperty(INSET_CUSTOM_PROPERTY_PREFIX + key);\n }\n }\n };\n }, [insets, portalRoot]);\n\n // adaptivity handler\n useIsomorphicLayoutEffect(() => {\n if (mode === 'partial') {\n return noop;\n }\n const className = sizeX !== SizeType.COMPACT ? vkuiSizeXClassNames[sizeX] : null;\n const container = mode === 'embedded' ? rootRef.current?.parentElement : document!.body;\n\n if (className === null || !container) {\n return noop;\n }\n\n container.classList.add(className);\n return () => {\n container.classList.remove(className);\n };\n }, [sizeX]);\n\n useIsomorphicLayoutEffect(() => {\n if (mode !== 'full' || appearance === undefined) {\n return noop;\n }\n document!.documentElement.style.setProperty('color-scheme', appearance);\n\n return () => document!.documentElement.style.removeProperty('color-scheme');\n }, [appearance]);\n\n const ScrollController = React.useMemo(\n () => (scroll === 'contain' ? ElementScrollController : GlobalScrollController),\n [scroll],\n );\n\n const content = (\n <AppRootContext.Provider\n value={{\n appRoot: rootRef,\n portalRoot,\n embedded: mode === 'embedded',\n keyboardInput: isKeyboardInputActive,\n mode,\n disablePortal,\n }}\n >\n <ScrollController elRef={rootRef}>\n <IconSettingsProvider classPrefix=\"vkui\">{children}</IconSettingsProvider>\n </ScrollController>\n </AppRootContext.Provider>\n );\n\n return mode === 'partial' ? (\n content\n ) : (\n <div\n ref={rootRef}\n className={classNames(\n styles['AppRoot'],\n hasPointer === undefined\n ? styles['AppRoot--pointer-none']\n : !hasPointer && styles['AppRoot--pointer-has-not'],\n className,\n )}\n {...props}\n >\n {content}\n </div>\n );\n};\n"],"names":["React","IconSettingsProvider","classNames","noop","useAdaptivity","useAppearance","useInsets","useKeyboardInputTracker","SizeType","useDOM","isRefObject","useIsomorphicLayoutEffect","AppRootContext","ElementScrollController","GlobalScrollController","styles","vkuiSizeXClassNames","none","REGULAR","INSET_CUSTOM_PROPERTY_PREFIX","AppRoot","children","mode","scroll","portalRoot","portalRootProp","disablePortal","className","props","isKeyboardInputActive","rootRef","useRef","setPortalRoot","useState","document","insets","appearance","hasPointer","sizeX","portal","current","createElement","body","appendChild","parentElement","removeChild","parent","classes","concat","classList","add","remove","documentElement","undefined","key","hasOwnProperty","inset","style","setProperty","removeProperty","COMPACT","container","ScrollController","useMemo","content","Provider","value","appRoot","embedded","keyboardInput","elRef","classPrefix","div","ref"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/AppRoot/AppRoot.tsx"],"sourcesContent":["import * as React from 'react';\nimport { IconSettingsProvider } from '@vkontakte/icons';\nimport { Insets } from '@vkontakte/vk-bridge';\nimport { classNames, noop } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useAppearance } from '../../hooks/useAppearance';\nimport { useInsets } from '../../hooks/useInsets';\nimport { useKeyboardInputTracker } from '../../hooks/useKeyboardInputTracker';\nimport { SizeType } from '../../lib/adaptivity';\nimport { useDOM } from '../../lib/dom';\nimport { isRefObject } from '../../lib/isRefObject';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport { AppRootContext } from './AppRootContext';\nimport { ElementScrollController, GlobalScrollController } from './ScrollContext';\nimport styles from './AppRoot.module.css';\n\nconst vkuiSizeXClassNames = {\n none: 'vkui--sizeX-none',\n [SizeType.REGULAR]: 'vkui--sizeX-regular',\n};\n\nconst INSET_CUSTOM_PROPERTY_PREFIX = `--vkui_internal--safe_area_inset_`;\n\n// Используйте classList, но будьте осторожны\n/* eslint-disable no-restricted-properties */\n\nexport interface AppRootProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Режим встраивания */\n mode?: 'partial' | 'embedded' | 'full';\n window?: Window;\n scroll?: 'global' | 'contain';\n /**\n * Кастомный root-элемент портала\n */\n portalRoot?: HTMLElement | React.RefObject<HTMLElement> | null;\n /** Disable portal for components */\n disablePortal?: boolean;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/AppRoot\n */\nexport const AppRoot = ({\n children,\n mode = 'full',\n scroll = 'global',\n portalRoot: portalRootProp = null,\n disablePortal,\n className,\n ...props\n}: AppRootProps) => {\n const isKeyboardInputActive = useKeyboardInputTracker();\n const rootRef = React.useRef<HTMLDivElement | null>(null);\n const [portalRoot, setPortalRoot] = React.useState<HTMLElement | null>(null);\n const { document } = useDOM();\n const insets = useInsets();\n const appearance = useAppearance();\n\n const { hasPointer, sizeX = 'none' } = useAdaptivity();\n\n // setup portal\n useIsomorphicLayoutEffect(() => {\n let portal: HTMLElement | null = null;\n if (portalRootProp) {\n if (isRefObject(portalRootProp)) {\n portal = portalRootProp.current;\n } else {\n portal = portalRootProp;\n }\n }\n if (!portal) {\n portal = document!.createElement('div');\n document!.body.appendChild(portal);\n }\n setPortalRoot(portal);\n return () => {\n if (!portalRootProp) {\n portal?.parentElement?.removeChild(portal);\n }\n };\n }, [portalRootProp]);\n\n // setup root classes\n useIsomorphicLayoutEffect(() => {\n if (mode === 'partial') {\n return noop;\n }\n\n const parent = rootRef.current?.parentElement;\n const classes = ['vkui__root'].concat(mode === 'embedded' ? 'vkui__root--embedded' : []);\n parent?.classList.add(...classes);\n\n return () => {\n parent?.classList.remove(...classes);\n };\n }, []);\n\n useIsomorphicLayoutEffect(() => {\n if (mode === 'full') {\n document!.documentElement.classList.add('vkui');\n\n return () => {\n document!.documentElement.classList.remove('vkui');\n };\n }\n\n return undefined;\n }, [document, mode]);\n\n // setup insets\n useIsomorphicLayoutEffect(() => {\n if (mode === 'partial' || !rootRef.current?.parentElement) {\n return noop;\n }\n\n const parent = rootRef.current.parentElement;\n\n let key: keyof Insets;\n for (key in insets) {\n if (insets.hasOwnProperty(key) && typeof insets[key] === 'number') {\n const inset = insets[key];\n parent.style.setProperty(INSET_CUSTOM_PROPERTY_PREFIX + key, `${inset}px`);\n portalRoot &&\n portalRoot.style.setProperty(INSET_CUSTOM_PROPERTY_PREFIX + key, `${inset}px`);\n }\n }\n\n return () => {\n let key: keyof Insets;\n for (key in insets) {\n if (insets.hasOwnProperty(key)) {\n parent.style.removeProperty(INSET_CUSTOM_PROPERTY_PREFIX + key);\n portalRoot && portalRoot.style.removeProperty(INSET_CUSTOM_PROPERTY_PREFIX + key);\n }\n }\n };\n }, [insets, portalRoot]);\n\n // adaptivity handler\n useIsomorphicLayoutEffect(() => {\n if (mode === 'partial') {\n return noop;\n }\n const className = sizeX !== SizeType.COMPACT ? vkuiSizeXClassNames[sizeX] : null;\n const container = mode === 'embedded' ? rootRef.current?.parentElement : document!.body;\n\n if (className === null || !container) {\n return noop;\n }\n\n container.classList.add(className);\n return () => {\n container.classList.remove(className);\n };\n }, [sizeX]);\n\n useIsomorphicLayoutEffect(() => {\n if (mode !== 'full' || appearance === undefined) {\n return noop;\n }\n document!.documentElement.style.setProperty('color-scheme', appearance);\n\n return () => document!.documentElement.style.removeProperty('color-scheme');\n }, [appearance]);\n\n const ScrollController = React.useMemo(\n () => (scroll === 'contain' ? ElementScrollController : GlobalScrollController),\n [scroll],\n );\n\n const content = (\n <AppRootContext.Provider\n value={{\n appRoot: rootRef,\n portalRoot,\n embedded: mode === 'embedded',\n keyboardInput: isKeyboardInputActive,\n mode,\n disablePortal,\n }}\n >\n <ScrollController elRef={rootRef}>\n <IconSettingsProvider classPrefix=\"vkui\">{children}</IconSettingsProvider>\n </ScrollController>\n </AppRootContext.Provider>\n );\n\n return mode === 'partial' ? (\n content\n ) : (\n <div\n ref={rootRef}\n className={classNames(\n styles['AppRoot'],\n hasPointer === undefined\n ? styles['AppRoot--pointer-none']\n : !hasPointer && styles['AppRoot--pointer-has-not'],\n className,\n )}\n {...props}\n >\n {content}\n </div>\n );\n};\n"],"names":["React","IconSettingsProvider","classNames","noop","useAdaptivity","useAppearance","useInsets","useKeyboardInputTracker","SizeType","useDOM","isRefObject","useIsomorphicLayoutEffect","AppRootContext","ElementScrollController","GlobalScrollController","styles","vkuiSizeXClassNames","none","REGULAR","INSET_CUSTOM_PROPERTY_PREFIX","AppRoot","children","mode","scroll","portalRoot","portalRootProp","disablePortal","className","props","isKeyboardInputActive","rootRef","useRef","setPortalRoot","useState","document","insets","appearance","hasPointer","sizeX","portal","current","createElement","body","appendChild","parentElement","removeChild","parent","classes","concat","classList","add","remove","documentElement","undefined","key","hasOwnProperty","inset","style","setProperty","removeProperty","COMPACT","container","ScrollController","useMemo","content","Provider","value","appRoot","embedded","keyboardInput","elRef","classPrefix","div","ref"],"mappings":"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"}
|
|
@@ -4,6 +4,12 @@ import { RemovableProps } from '../Removable/Removable';
|
|
|
4
4
|
export interface FormItemProps extends React.AllHTMLAttributes<HTMLElement>, HasRootRef<HTMLElement>, HasComponent, RemovableProps {
|
|
5
5
|
top?: React.ReactNode;
|
|
6
6
|
bottom?: React.ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* Передаётся при использовании `bottom`.
|
|
9
|
+
*
|
|
10
|
+
* Должен совпадать с `aria-describedby`, который передаётся в компонент, отвечающий за пользовательский ввод.
|
|
11
|
+
*/
|
|
12
|
+
bottomId?: string;
|
|
7
13
|
status?: 'default' | 'error' | 'valid';
|
|
8
14
|
/**
|
|
9
15
|
* Дает возможность удалить `FormItem`. Рекомендуется использовать только для `Input` или `Select`.
|
|
@@ -15,4 +21,4 @@ export interface FormItemProps extends React.AllHTMLAttributes<HTMLElement>, Has
|
|
|
15
21
|
/**
|
|
16
22
|
* @see https://vkcom.github.io/VKUI/#/FormItem
|
|
17
23
|
*/
|
|
18
|
-
export declare const FormItem: ({ children, top, bottom, status, Component, removable, onRemove, removePlaceholder, getRootRef, className, htmlFor, ...restProps }: FormItemProps) => React.JSX.Element;
|
|
24
|
+
export declare const FormItem: ({ children, top, bottom, status, Component, removable, onRemove, removePlaceholder, getRootRef, className, htmlFor, bottomId, ...restProps }: FormItemProps) => React.JSX.Element;
|
|
@@ -13,7 +13,7 @@ const sizeYClassNames = {
|
|
|
13
13
|
};
|
|
14
14
|
/**
|
|
15
15
|
* @see https://vkcom.github.io/VKUI/#/FormItem
|
|
16
|
-
*/ export const FormItem = ({ children, top, bottom, status = 'default', Component = 'div', removable, onRemove = noop, removePlaceholder = 'Удалить', getRootRef, className, htmlFor, ...restProps })=>{
|
|
16
|
+
*/ export const FormItem = ({ children, top, bottom, status = 'default', Component = 'div', removable, onRemove = noop, removePlaceholder = 'Удалить', getRootRef, className, htmlFor, bottomId, ...restProps })=>{
|
|
17
17
|
const rootEl = useExternRef(getRootRef);
|
|
18
18
|
const { sizeY = 'none' } = useAdaptivity();
|
|
19
19
|
const wrappedChildren = /*#__PURE__*/ React.createElement(React.Fragment, null, hasReactNode(top) && /*#__PURE__*/ React.createElement(Subhead, {
|
|
@@ -21,7 +21,9 @@ const sizeYClassNames = {
|
|
|
21
21
|
Component: htmlFor ? 'label' : 'h5',
|
|
22
22
|
htmlFor: htmlFor
|
|
23
23
|
}, top), children, hasReactNode(bottom) && /*#__PURE__*/ React.createElement(Footnote, {
|
|
24
|
-
className: styles['FormItem__bottom']
|
|
24
|
+
className: styles['FormItem__bottom'],
|
|
25
|
+
id: bottomId,
|
|
26
|
+
role: status === 'error' ? 'alert' : undefined
|
|
25
27
|
}, bottom));
|
|
26
28
|
return /*#__PURE__*/ React.createElement(Component, {
|
|
27
29
|
...restProps,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/FormItem/FormItem.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames, hasReactNode, noop } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { SizeType } from '../../lib/adaptivity';\nimport { HasComponent, HasRootRef } from '../../types';\nimport { Removable, RemovableProps } from '../Removable/Removable';\nimport { Footnote } from '../Typography/Footnote/Footnote';\nimport { Subhead } from '../Typography/Subhead/Subhead';\nimport styles from './FormItem.module.css';\n\nconst sizeYClassNames = {\n none: classNames(styles['FormItem--sizeY-none'], 'vkuiInternalFormItem--sizeY-none'),\n [SizeType.COMPACT]: classNames(\n styles['FormItem--sizeY-compact'],\n 'vkuiInternalFormItem--sizeY-compact',\n ),\n};\n\nexport interface FormItemProps\n extends React.AllHTMLAttributes<HTMLElement>,\n HasRootRef<HTMLElement>,\n HasComponent,\n RemovableProps {\n top?: React.ReactNode;\n bottom?: React.ReactNode;\n status?: 'default' | 'error' | 'valid';\n /**\n * Дает возможность удалить `FormItem`. Рекомендуется использовать только для `Input` или `Select`.\n *\n * Режим `indent` предназначен для визуального отступа\n */\n removable?: boolean | 'indent';\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/FormItem\n */\nexport const FormItem = ({\n children,\n top,\n bottom,\n status = 'default',\n Component = 'div',\n removable,\n onRemove = noop,\n removePlaceholder = 'Удалить',\n getRootRef,\n className,\n htmlFor,\n ...restProps\n}: FormItemProps) => {\n const rootEl = useExternRef(getRootRef);\n const { sizeY = 'none' } = useAdaptivity();\n\n const wrappedChildren = (\n <React.Fragment>\n {hasReactNode(top) && (\n <Subhead\n className={styles['FormItem__top']}\n Component={htmlFor ? 'label' : 'h5'}\n htmlFor={htmlFor}\n >\n {top}\n </Subhead>\n )}\n {children}\n {hasReactNode(bottom) && <Footnote
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/FormItem/FormItem.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames, hasReactNode, noop } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { SizeType } from '../../lib/adaptivity';\nimport { HasComponent, HasRootRef } from '../../types';\nimport { Removable, RemovableProps } from '../Removable/Removable';\nimport { Footnote } from '../Typography/Footnote/Footnote';\nimport { Subhead } from '../Typography/Subhead/Subhead';\nimport styles from './FormItem.module.css';\n\nconst sizeYClassNames = {\n none: classNames(styles['FormItem--sizeY-none'], 'vkuiInternalFormItem--sizeY-none'),\n [SizeType.COMPACT]: classNames(\n styles['FormItem--sizeY-compact'],\n 'vkuiInternalFormItem--sizeY-compact',\n ),\n};\n\nexport interface FormItemProps\n extends React.AllHTMLAttributes<HTMLElement>,\n HasRootRef<HTMLElement>,\n HasComponent,\n RemovableProps {\n top?: React.ReactNode;\n bottom?: React.ReactNode;\n /**\n * Передаётся при использовании `bottom`.\n *\n * Должен совпадать с `aria-describedby`, который передаётся в компонент, отвечающий за пользовательский ввод.\n */\n bottomId?: string;\n status?: 'default' | 'error' | 'valid';\n /**\n * Дает возможность удалить `FormItem`. Рекомендуется использовать только для `Input` или `Select`.\n *\n * Режим `indent` предназначен для визуального отступа\n */\n removable?: boolean | 'indent';\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/FormItem\n */\nexport const FormItem = ({\n children,\n top,\n bottom,\n status = 'default',\n Component = 'div',\n removable,\n onRemove = noop,\n removePlaceholder = 'Удалить',\n getRootRef,\n className,\n htmlFor,\n bottomId,\n ...restProps\n}: FormItemProps) => {\n const rootEl = useExternRef(getRootRef);\n const { sizeY = 'none' } = useAdaptivity();\n\n const wrappedChildren = (\n <React.Fragment>\n {hasReactNode(top) && (\n <Subhead\n className={styles['FormItem__top']}\n Component={htmlFor ? 'label' : 'h5'}\n htmlFor={htmlFor}\n >\n {top}\n </Subhead>\n )}\n {children}\n {hasReactNode(bottom) && (\n <Footnote\n className={styles['FormItem__bottom']}\n id={bottomId}\n role={status === 'error' ? 'alert' : undefined}\n >\n {bottom}\n </Footnote>\n )}\n </React.Fragment>\n );\n\n return (\n <Component\n {...restProps}\n ref={rootEl}\n className={classNames(\n styles['FormItem'],\n 'vkuiInternalFormItem',\n status !== 'default' &&\n {\n error: classNames(\n styles['FormItem--status-error'],\n 'vkuiInternalFormItem--status-error',\n ),\n valid: classNames(\n styles['FormItem--status-valid'],\n 'vkuiInternalFormItem--status-valid',\n ),\n }[status],\n sizeY !== SizeType.REGULAR && sizeYClassNames[sizeY],\n hasReactNode(top) &&\n classNames(styles['FormItem--withTop'], 'vkuiInternalFormItem--withTop'),\n removable && classNames(styles['FormItem--removable'], 'vkuiInternalFormItem--removable'),\n className,\n )}\n >\n {removable ? (\n <Removable\n align=\"start\"\n onRemove={(e) => {\n if (rootEl?.current) {\n onRemove(e, rootEl.current);\n }\n }}\n removePlaceholder={removePlaceholder}\n indent={removable === 'indent'}\n >\n <div\n className={classNames(styles['FormItem__removable'], 'vkuiInternalFormItem__removable')}\n >\n {wrappedChildren}\n </div>\n </Removable>\n ) : (\n wrappedChildren\n )}\n </Component>\n );\n};\n"],"names":["React","classNames","hasReactNode","noop","useAdaptivity","useExternRef","SizeType","Removable","Footnote","Subhead","styles","sizeYClassNames","none","COMPACT","FormItem","children","top","bottom","status","Component","removable","onRemove","removePlaceholder","getRootRef","className","htmlFor","bottomId","restProps","rootEl","sizeY","wrappedChildren","Fragment","id","role","undefined","ref","error","valid","REGULAR","align","e","current","indent","div"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,UAAU,EAAEC,YAAY,EAAEC,IAAI,QAAQ,kBAAkB;AACjE,SAASC,aAAa,QAAQ,4BAA4B;AAC1D,SAASC,YAAY,QAAQ,2BAA2B;AACxD,SAASC,QAAQ,QAAQ,uBAAuB;AAEhD,SAASC,SAAS,QAAwB,yBAAyB;AACnE,SAASC,QAAQ,QAAQ,kCAAkC;AAC3D,SAASC,OAAO,QAAQ,gCAAgC;AACxD,OAAOC,YAAY,wBAAwB;AAE3C,MAAMC,kBAAkB;IACtBC,MAAMX,WAAWS,MAAM,CAAC,uBAAuB,EAAE;IACjD,CAACJ,SAASO,OAAO,CAAC,EAAEZ,WAClBS,MAAM,CAAC,0BAA0B,EACjC;AAEJ;AAwBA;;CAEC,GACD,OAAO,MAAMI,WAAW,CAAC,EACvBC,QAAQ,EACRC,GAAG,EACHC,MAAM,EACNC,SAAS,SAAS,EAClBC,YAAY,KAAK,EACjBC,SAAS,EACTC,WAAWlB,IAAI,EACfmB,oBAAoB,SAAS,EAC7BC,UAAU,EACVC,SAAS,EACTC,OAAO,EACPC,QAAQ,EACR,GAAGC,WACW;IACd,MAAMC,SAASvB,aAAakB;IAC5B,MAAM,EAAEM,QAAQ,MAAM,EAAE,GAAGzB;IAE3B,MAAM0B,gCACJ,oBAAC9B,MAAM+B,QAAQ,QACZ7B,aAAac,sBACZ,oBAACP;QACCe,WAAWd,MAAM,CAAC,gBAAgB;QAClCS,WAAWM,UAAU,UAAU;QAC/BA,SAASA;OAERT,MAGJD,UACAb,aAAae,yBACZ,oBAACT;QACCgB,WAAWd,MAAM,CAAC,mBAAmB;QACrCsB,IAAIN;QACJO,MAAMf,WAAW,UAAU,UAAUgB;OAEpCjB;IAMT,qBACE,oBAACE;QACE,GAAGQ,SAAS;QACbQ,KAAKP;QACLJ,WAAWvB,WACTS,MAAM,CAAC,WAAW,EAClB,wBACAQ,WAAW,aACT,CAAA;YACEkB,OAAOnC,WACLS,MAAM,CAAC,yBAAyB,EAChC;YAEF2B,OAAOpC,WACLS,MAAM,CAAC,yBAAyB,EAChC;QAEJ,CAAA,CAAC,CAACQ,OAAO,EACXW,UAAUvB,SAASgC,OAAO,IAAI3B,eAAe,CAACkB,MAAM,EACpD3B,aAAac,QACXf,WAAWS,MAAM,CAAC,oBAAoB,EAAE,kCAC1CU,aAAanB,WAAWS,MAAM,CAAC,sBAAsB,EAAE,oCACvDc;OAGDJ,0BACC,oBAACb;QACCgC,OAAM;QACNlB,UAAU,CAACmB;YACT,IAAIZ,QAAQa,SAAS;gBACnBpB,SAASmB,GAAGZ,OAAOa,OAAO;YAC5B;QACF;QACAnB,mBAAmBA;QACnBoB,QAAQtB,cAAc;qBAEtB,oBAACuB;QACCnB,WAAWvB,WAAWS,MAAM,CAAC,sBAAsB,EAAE;OAEpDoB,oBAILA;AAIR,EAAE"}
|
|
@@ -49,10 +49,8 @@ import styles from './Search.module.css';
|
|
|
49
49
|
const onIconCancelClickStart = React.useCallback((e)=>{
|
|
50
50
|
e.originalEvent.preventDefault();
|
|
51
51
|
inputRef.current?.focus();
|
|
52
|
-
onCancel();
|
|
53
52
|
}, [
|
|
54
|
-
inputRef
|
|
55
|
-
onCancel
|
|
53
|
+
inputRef
|
|
56
54
|
]);
|
|
57
55
|
return /*#__PURE__*/ React.createElement("div", {
|
|
58
56
|
className: classNames('vkuiInternalSearch', styles['Search'], sizeY === 'none' && styles['Search--sizeY-none'], sizeY === SizeType.COMPACT && styles['Search--sizeY-compact'], isFocused && styles['Search--focused'], value && styles['Search--has-value'], after && styles['Search--has-after'], icon && styles['Search--has-icon'], className),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Search/Search.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Icon16Clear, Icon16SearchOutline, Icon24Cancel } from '@vkontakte/icons';\nimport { classNames, noop } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useBooleanState } from '../../hooks/useBooleanState';\nimport { useEnsuredControl } from '../../hooks/useEnsuredControl';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { SizeType } from '../../lib/adaptivity';\nimport { Platform } from '../../lib/platform';\nimport { VKUITouchEvent } from '../../lib/touch';\nimport { HasRef } from '../../types';\nimport { Button } from '../Button/Button';\nimport { IconButton } from '../IconButton/IconButton';\nimport { TouchEvent } from '../Touch/Touch';\nimport { Headline } from '../Typography/Headline/Headline';\nimport styles from './Search.module.css';\n\nexport interface SearchProps\n extends React.InputHTMLAttributes<HTMLInputElement>,\n HasRef<HTMLInputElement> {\n /**\n * iOS only. Текст кнопки \"отмена\", которая чистит текстовое поле и убирает фокус.\n */\n after?: React.ReactNode;\n before?: React.ReactNode;\n icon?: React.ReactNode;\n onIconClick?: (e: VKUITouchEvent) => void;\n defaultValue?: string;\n iconAriaLabel?: string;\n clearAriaLabel?: string;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Search\n */\nexport const Search = ({\n before = <Icon16SearchOutline />,\n className,\n defaultValue = '',\n placeholder = 'Поиск',\n after = 'Отмена',\n getRef,\n icon,\n onIconClick = noop,\n style,\n autoComplete = 'off',\n onChange: onChangeProp,\n value: valueProp,\n iconAriaLabel,\n clearAriaLabel = 'Очистить',\n ...inputProps\n}: SearchProps) => {\n const inputRef = useExternRef(getRef);\n const {\n value: isFocused,\n setTrue: setFocusedTrue,\n setFalse: setFocusedFalse,\n } = useBooleanState(false);\n\n const [value, onChange] = useEnsuredControl({\n defaultValue,\n onChange: onChangeProp,\n value: valueProp,\n });\n const { sizeY = 'none' } = useAdaptivity();\n const platform = usePlatform();\n\n const onFocus = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedTrue();\n inputProps.onFocus && inputProps.onFocus(e);\n };\n\n const onBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedFalse();\n inputProps.onBlur && inputProps.onBlur(e);\n };\n\n const onCancel = React.useCallback(() => {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n 'value',\n )?.set;\n nativeInputValueSetter?.call(inputRef.current, '');\n\n const ev2 = new Event('input', { bubbles: true });\n inputRef.current?.dispatchEvent(ev2);\n }, [inputRef]);\n\n const onIconClickStart = React.useCallback(\n (e: TouchEvent) => onIconClick(e.originalEvent),\n [onIconClick],\n );\n\n const onIconCancelClickStart = React.useCallback(\n (e: TouchEvent) => {\n e.originalEvent.preventDefault();\n inputRef.current?.focus();\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Search/Search.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Icon16Clear, Icon16SearchOutline, Icon24Cancel } from '@vkontakte/icons';\nimport { classNames, noop } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useBooleanState } from '../../hooks/useBooleanState';\nimport { useEnsuredControl } from '../../hooks/useEnsuredControl';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { SizeType } from '../../lib/adaptivity';\nimport { Platform } from '../../lib/platform';\nimport { VKUITouchEvent } from '../../lib/touch';\nimport { HasRef } from '../../types';\nimport { Button } from '../Button/Button';\nimport { IconButton } from '../IconButton/IconButton';\nimport { TouchEvent } from '../Touch/Touch';\nimport { Headline } from '../Typography/Headline/Headline';\nimport styles from './Search.module.css';\n\nexport interface SearchProps\n extends React.InputHTMLAttributes<HTMLInputElement>,\n HasRef<HTMLInputElement> {\n /**\n * iOS only. Текст кнопки \"отмена\", которая чистит текстовое поле и убирает фокус.\n */\n after?: React.ReactNode;\n before?: React.ReactNode;\n icon?: React.ReactNode;\n onIconClick?: (e: VKUITouchEvent) => void;\n defaultValue?: string;\n iconAriaLabel?: string;\n clearAriaLabel?: string;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Search\n */\nexport const Search = ({\n before = <Icon16SearchOutline />,\n className,\n defaultValue = '',\n placeholder = 'Поиск',\n after = 'Отмена',\n getRef,\n icon,\n onIconClick = noop,\n style,\n autoComplete = 'off',\n onChange: onChangeProp,\n value: valueProp,\n iconAriaLabel,\n clearAriaLabel = 'Очистить',\n ...inputProps\n}: SearchProps) => {\n const inputRef = useExternRef(getRef);\n const {\n value: isFocused,\n setTrue: setFocusedTrue,\n setFalse: setFocusedFalse,\n } = useBooleanState(false);\n\n const [value, onChange] = useEnsuredControl({\n defaultValue,\n onChange: onChangeProp,\n value: valueProp,\n });\n const { sizeY = 'none' } = useAdaptivity();\n const platform = usePlatform();\n\n const onFocus = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedTrue();\n inputProps.onFocus && inputProps.onFocus(e);\n };\n\n const onBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedFalse();\n inputProps.onBlur && inputProps.onBlur(e);\n };\n\n const onCancel = React.useCallback(() => {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n 'value',\n )?.set;\n nativeInputValueSetter?.call(inputRef.current, '');\n\n const ev2 = new Event('input', { bubbles: true });\n inputRef.current?.dispatchEvent(ev2);\n }, [inputRef]);\n\n const onIconClickStart = React.useCallback(\n (e: TouchEvent) => onIconClick(e.originalEvent),\n [onIconClick],\n );\n\n const onIconCancelClickStart = React.useCallback(\n (e: TouchEvent) => {\n e.originalEvent.preventDefault();\n inputRef.current?.focus();\n },\n [inputRef],\n );\n\n return (\n <div\n className={classNames(\n 'vkuiInternalSearch',\n styles['Search'],\n sizeY === 'none' && styles['Search--sizeY-none'],\n sizeY === SizeType.COMPACT && styles['Search--sizeY-compact'],\n isFocused && styles['Search--focused'],\n value && styles['Search--has-value'],\n after && styles['Search--has-after'],\n icon && styles['Search--has-icon'],\n className,\n )}\n style={style}\n >\n <div className={styles['Search__field']}>\n <label className={styles['Search__control']}>\n {before}\n <Headline\n Component=\"input\"\n type=\"search\"\n level=\"1\"\n weight=\"3\"\n {...inputProps}\n placeholder={placeholder}\n autoComplete={autoComplete}\n getRootRef={inputRef}\n className={styles['Search__input']}\n onFocus={onFocus}\n onBlur={onBlur}\n onChange={onChange}\n value={value}\n />\n </label>\n <div className={styles['Search__icons']}>\n {icon && (\n <IconButton\n hoverMode=\"opacity\"\n onStart={onIconClickStart}\n className={styles['Search__icon']}\n onFocus={setFocusedTrue}\n onBlur={setFocusedFalse}\n aria-label={iconAriaLabel}\n >\n {icon}\n </IconButton>\n )}\n {!!value && (\n <IconButton\n hoverMode=\"opacity\"\n onStart={onIconCancelClickStart}\n onClick={onCancel}\n className={styles['Search__icon']}\n aria-label={clearAriaLabel}\n >\n {platform === Platform.IOS ? <Icon16Clear /> : <Icon24Cancel />}\n </IconButton>\n )}\n </div>\n </div>\n {platform === Platform.IOS && after && (\n <Button\n mode=\"tertiary\"\n size=\"m\"\n className={styles['Search__after']}\n focusVisibleMode=\"inside\"\n onClick={onCancel}\n onFocus={setFocusedTrue}\n onBlur={setFocusedFalse}\n >\n <span className={styles['Search__afterText']}>{after}</span>\n </Button>\n )}\n </div>\n );\n};\n"],"names":["React","Icon16Clear","Icon16SearchOutline","Icon24Cancel","classNames","noop","useAdaptivity","useBooleanState","useEnsuredControl","useExternRef","usePlatform","SizeType","Platform","Button","IconButton","Headline","styles","Search","before","className","defaultValue","placeholder","after","getRef","icon","onIconClick","style","autoComplete","onChange","onChangeProp","value","valueProp","iconAriaLabel","clearAriaLabel","inputProps","inputRef","isFocused","setTrue","setFocusedTrue","setFalse","setFocusedFalse","sizeY","platform","onFocus","e","onBlur","onCancel","useCallback","nativeInputValueSetter","Object","getOwnPropertyDescriptor","HTMLInputElement","prototype","set","call","current","ev2","Event","bubbles","dispatchEvent","onIconClickStart","originalEvent","onIconCancelClickStart","preventDefault","focus","div","COMPACT","label","Component","type","level","weight","getRootRef","hoverMode","onStart","aria-label","onClick","IOS","mode","size","focusVisibleMode","span"],"mappings":"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"}
|
|
@@ -70,6 +70,9 @@
|
|
|
70
70
|
max-width: 100%;
|
|
71
71
|
flex-grow: 1;
|
|
72
72
|
min-width: 0;
|
|
73
|
+
width: -webkit-fill-available;
|
|
74
|
+
width: -moz-available;
|
|
75
|
+
width: stretch; /* автопрефиксер добавит фолбеки https://caniuse.com/mdn-css_properties_width_stretch */
|
|
73
76
|
background-color: transparent;
|
|
74
77
|
color: var(--vkui--color_text_primary);
|
|
75
78
|
}
|
|
@@ -22,13 +22,21 @@ const defaultScrollToRight = (x)=>x + 240;
|
|
|
22
22
|
}
|
|
23
23
|
return /*#__PURE__*/ React.createElement("div", {
|
|
24
24
|
...restProps,
|
|
25
|
-
className: classNames(
|
|
25
|
+
className: classNames(// TODO: [>=6]
|
|
26
|
+
// Заменить у SubnavigationButton `display: inline-block` на `width: 100%`
|
|
27
|
+
// и удалить применение селектора в `SubnavigationButton.module.css`.
|
|
28
|
+
// 2. Заменить глобальный селектор на CSS Modules `styles['SubnavigationBar--mode-fixed']`
|
|
29
|
+
// mode !== 'fixed' && classNames('vkuiInternalSubnavigationBar--mode-fixed')
|
|
30
|
+
mode === 'fixed' && classNames('vkuiInternalSubnavigationBar--mode-fixed'), className)
|
|
26
31
|
}, /*#__PURE__*/ React.createElement(ScrollWrapper, {
|
|
27
32
|
className: styles['SubnavigationBar__in'],
|
|
28
33
|
...scrollWrapperProps
|
|
29
|
-
}, /*#__PURE__*/ React.createElement("
|
|
34
|
+
}, /*#__PURE__*/ React.createElement("ul", {
|
|
30
35
|
className: styles['SubnavigationBar__scrollIn']
|
|
31
|
-
}, children)
|
|
36
|
+
}, React.Children.map(children, (child, idx)=>/*#__PURE__*/ React.createElement("li", {
|
|
37
|
+
key: idx,
|
|
38
|
+
className: styles['SubnavigationBar__item']
|
|
39
|
+
}, child)))));
|
|
32
40
|
};
|
|
33
41
|
|
|
34
42
|
//# sourceMappingURL=SubnavigationBar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/SubnavigationBar/SubnavigationBar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport {\n HorizontalScroll,\n HorizontalScrollProps,\n ScrollPositionHandler,\n} from '../HorizontalScroll/HorizontalScroll';\nimport styles from './SubnavigationBar.module.css';\n\nexport interface SubnavigationBarProps\n extends React.HTMLAttributes<HTMLDivElement>,\n Pick<\n HorizontalScrollProps,\n 'showArrows' | 'getScrollToLeft' | 'getScrollToRight' | 'scrollAnimationDuration'\n > {\n mode?: 'fixed' | 'overflow';\n}\n\nconst defaultScrollToLeft: ScrollPositionHandler = (x) => x - 240;\n\nconst defaultScrollToRight: ScrollPositionHandler = (x) => x + 240;\n\n/**\n * @see https://vkcom.github.io/VKUI/#/SubnavigationBar\n */\nexport const SubnavigationBar = ({\n mode = 'overflow',\n children,\n showArrows = true,\n getScrollToLeft = defaultScrollToLeft,\n getScrollToRight = defaultScrollToRight,\n scrollAnimationDuration,\n className,\n ...restProps\n}: SubnavigationBarProps) => {\n let ScrollWrapper: React.ElementType;\n let scrollWrapperProps = {};\n\n if (mode === 'fixed') {\n ScrollWrapper = 'div';\n } else {\n ScrollWrapper = HorizontalScroll;\n scrollWrapperProps = {\n showArrows,\n getScrollToLeft,\n getScrollToRight,\n scrollAnimationDuration,\n };\n }\n\n return (\n <div\n {...restProps}\n className={classNames(\n 'vkuiInternalSubnavigationBar'
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/SubnavigationBar/SubnavigationBar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport {\n HorizontalScroll,\n HorizontalScrollProps,\n ScrollPositionHandler,\n} from '../HorizontalScroll/HorizontalScroll';\nimport styles from './SubnavigationBar.module.css';\n\nexport interface SubnavigationBarProps\n extends React.HTMLAttributes<HTMLDivElement>,\n Pick<\n HorizontalScrollProps,\n 'showArrows' | 'getScrollToLeft' | 'getScrollToRight' | 'scrollAnimationDuration'\n > {\n mode?: 'fixed' | 'overflow';\n}\n\nconst defaultScrollToLeft: ScrollPositionHandler = (x) => x - 240;\n\nconst defaultScrollToRight: ScrollPositionHandler = (x) => x + 240;\n\n/**\n * @see https://vkcom.github.io/VKUI/#/SubnavigationBar\n */\nexport const SubnavigationBar = ({\n mode = 'overflow',\n children,\n showArrows = true,\n getScrollToLeft = defaultScrollToLeft,\n getScrollToRight = defaultScrollToRight,\n scrollAnimationDuration,\n className,\n ...restProps\n}: SubnavigationBarProps) => {\n let ScrollWrapper: React.ElementType;\n let scrollWrapperProps = {};\n\n if (mode === 'fixed') {\n ScrollWrapper = 'div';\n } else {\n ScrollWrapper = HorizontalScroll;\n scrollWrapperProps = {\n showArrows,\n getScrollToLeft,\n getScrollToRight,\n scrollAnimationDuration,\n };\n }\n\n return (\n <div\n {...restProps}\n className={classNames(\n // TODO: [>=6]\n // Заменить у SubnavigationButton `display: inline-block` на `width: 100%`\n // и удалить применение селектора в `SubnavigationButton.module.css`.\n // 2. Заменить глобальный селектор на CSS Modules `styles['SubnavigationBar--mode-fixed']`\n // mode !== 'fixed' && classNames('vkuiInternalSubnavigationBar--mode-fixed')\n mode === 'fixed' && classNames('vkuiInternalSubnavigationBar--mode-fixed'),\n className,\n )}\n >\n <ScrollWrapper className={styles['SubnavigationBar__in']} {...scrollWrapperProps}>\n <ul className={styles['SubnavigationBar__scrollIn']}>\n {React.Children.map(children, (child, idx) => (\n <li key={idx} className={styles['SubnavigationBar__item']}>\n {child}\n </li>\n ))}\n </ul>\n </ScrollWrapper>\n </div>\n );\n};\n"],"names":["React","classNames","HorizontalScroll","styles","defaultScrollToLeft","x","defaultScrollToRight","SubnavigationBar","mode","children","showArrows","getScrollToLeft","getScrollToRight","scrollAnimationDuration","className","restProps","ScrollWrapper","scrollWrapperProps","div","ul","Children","map","child","idx","li","key"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,UAAU,QAAQ,kBAAkB;AAC7C,SACEC,gBAAgB,QAGX,uCAAuC;AAC9C,OAAOC,YAAY,gCAAgC;AAWnD,MAAMC,sBAA6C,CAACC,IAAMA,IAAI;AAE9D,MAAMC,uBAA8C,CAACD,IAAMA,IAAI;AAE/D;;CAEC,GACD,OAAO,MAAME,mBAAmB,CAAC,EAC/BC,OAAO,UAAU,EACjBC,QAAQ,EACRC,aAAa,IAAI,EACjBC,kBAAkBP,mBAAmB,EACrCQ,mBAAmBN,oBAAoB,EACvCO,uBAAuB,EACvBC,SAAS,EACT,GAAGC,WACmB;IACtB,IAAIC;IACJ,IAAIC,qBAAqB,CAAC;IAE1B,IAAIT,SAAS,SAAS;QACpBQ,gBAAgB;IAClB,OAAO;QACLA,gBAAgBd;QAChBe,qBAAqB;YACnBP;YACAC;YACAC;YACAC;QACF;IACF;IAEA,qBACE,oBAACK;QACE,GAAGH,SAAS;QACbD,WAAWb,WACT,cAAc;QACd,0EAA0E;QAC1E,qEAAqE;QACrE,0FAA0F;QAC1F,6EAA6E;QAC7EO,SAAS,WAAWP,WAAW,6CAC/Ba;qBAGF,oBAACE;QAAcF,WAAWX,MAAM,CAAC,uBAAuB;QAAG,GAAGc,kBAAkB;qBAC9E,oBAACE;QAAGL,WAAWX,MAAM,CAAC,6BAA6B;OAChDH,MAAMoB,QAAQ,CAACC,GAAG,CAACZ,UAAU,CAACa,OAAOC,oBACpC,oBAACC;YAAGC,KAAKF;YAAKT,WAAWX,MAAM,CAAC,yBAAyB;WACtDmB;AAOf,EAAE"}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
.SubnavigationBar__scrollIn {
|
|
7
|
-
|
|
8
|
-
padding
|
|
7
|
+
margin: 0;
|
|
8
|
+
padding: calc(var(--vkui--size_subnavigation_bar_padding_vertical--regular) + 8px) 0;
|
|
9
9
|
display: flex;
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -14,3 +14,22 @@
|
|
|
14
14
|
content: '';
|
|
15
15
|
min-width: var(--vkui--size_base_padding_horizontal--regular);
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
.SubnavigationBar__item {
|
|
19
|
+
list-style-type: none;
|
|
20
|
+
display: flex;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.SubnavigationBar__item + .SubnavigationBar__item {
|
|
24
|
+
margin-left: var(--vkui--size_subnavigation_bar_gap--regular);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* CMP:
|
|
29
|
+
* SubnavigationBar
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
:global(.vkuiInternalSubnavigationBar--mode-fixed) .SubnavigationBar__item {
|
|
33
|
+
flex: 1;
|
|
34
|
+
min-width: 0;
|
|
35
|
+
}
|
|
@@ -151,15 +151,6 @@
|
|
|
151
151
|
--vkui_internal--counter_inherit_color: var(--vkui--color_text_accent_themed);
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
/**
|
|
155
|
-
* CMP:
|
|
156
|
-
* SubnavigationBar
|
|
157
|
-
*/
|
|
158
|
-
|
|
159
|
-
:global(.vkuiInternalSubnavigationBar) .SubnavigationButton + .SubnavigationButton {
|
|
160
|
-
margin-left: var(--vkui--size_subnavigation_bar_gap--regular);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
154
|
:global(.vkuiInternalSubnavigationBar--mode-fixed) .SubnavigationButton {
|
|
164
155
|
flex: 1;
|
|
165
156
|
min-width: 0;
|
|
@@ -3,19 +3,30 @@ export function precisionRound(number, precision = 1) {
|
|
|
3
3
|
let factor = Math.pow(10, precision);
|
|
4
4
|
return Math.round(number * factor) / factor;
|
|
5
5
|
}
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Решение скопировано без изменений у MUI:
|
|
8
|
+
* https://github.com/mui/material-ui/blob/v5.13.7/packages/mui-base/src/useSlider/useSlider.ts#L89-L105
|
|
9
|
+
*/ function getDecimalPrecision(num) {
|
|
10
|
+
// This handles the case when num is very small (0.00000001), js will turn this into 1e-8.
|
|
11
|
+
// When num is bigger than 1 or less than -1 it won't get converted to this notation so it's fine.
|
|
12
|
+
if (Math.abs(num) < 1) {
|
|
13
|
+
const parts = num.toExponential().split('e-');
|
|
14
|
+
const matissaDecimalPart = parts[0].split('.')[1];
|
|
15
|
+
return (matissaDecimalPart ? matissaDecimalPart.length : 0) + parseInt(parts[1], 10);
|
|
16
|
+
}
|
|
17
|
+
const decimalPart = num.toString().split('.')[1];
|
|
18
|
+
return decimalPart ? decimalPart.length : 0;
|
|
19
|
+
}
|
|
20
|
+
function roundValueToStep(value, step, min) {
|
|
21
|
+
const nearest = Math.round((value - min) / step) * step + min;
|
|
22
|
+
return Number(nearest.toFixed(getDecimalPrecision(step)));
|
|
8
23
|
}
|
|
9
24
|
function decimatedClamp(val, min, max, step) {
|
|
10
25
|
if (step == null || step <= 0) {
|
|
11
26
|
return clamp(val, min, max);
|
|
12
27
|
}
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
const decimatedOffset = precisionRound(Math.round((val - min) / step) * step, prec);
|
|
16
|
-
// Round range length _down_ to nearest min + k2 * step
|
|
17
|
-
const decimatedRange = precisionRound(Math.floor((max - min) / step) * step, prec);
|
|
18
|
-
return min + clamp(decimatedOffset, 0, decimatedRange);
|
|
28
|
+
const roundedValue = roundValueToStep(val, step, min);
|
|
29
|
+
return clamp(roundedValue, min, max);
|
|
19
30
|
}
|
|
20
31
|
export function rescale(value, from, to, options = {}) {
|
|
21
32
|
const scaled = (value - from[0]) / (from[1] - from[0]) * (to[1] - to[0]) + to[0];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/helpers/math.ts"],"sourcesContent":["export const clamp = (value: number, min: number, max: number) =>\n Math.max(min, Math.min(value, max));\n\nexport function precisionRound(number: number, precision = 1) {\n let factor = Math.pow(10, precision);\n return Math.round(number * factor) / factor;\n}\n\nfunction
|
|
1
|
+
{"version":3,"sources":["../../../src/helpers/math.ts"],"sourcesContent":["export const clamp = (value: number, min: number, max: number) =>\n Math.max(min, Math.min(value, max));\n\nexport function precisionRound(number: number, precision = 1) {\n let factor = Math.pow(10, precision);\n return Math.round(number * factor) / factor;\n}\n\n/**\n * Решение скопировано без изменений у MUI:\n * https://github.com/mui/material-ui/blob/v5.13.7/packages/mui-base/src/useSlider/useSlider.ts#L89-L105\n */\nfunction getDecimalPrecision(num: number) {\n // This handles the case when num is very small (0.00000001), js will turn this into 1e-8.\n // When num is bigger than 1 or less than -1 it won't get converted to this notation so it's fine.\n if (Math.abs(num) < 1) {\n const parts = num.toExponential().split('e-');\n const matissaDecimalPart = parts[0].split('.')[1];\n return (matissaDecimalPart ? matissaDecimalPart.length : 0) + parseInt(parts[1], 10);\n }\n\n const decimalPart = num.toString().split('.')[1];\n return decimalPart ? decimalPart.length : 0;\n}\n\nfunction roundValueToStep(value: number, step: number, min: number) {\n const nearest = Math.round((value - min) / step) * step + min;\n return Number(nearest.toFixed(getDecimalPrecision(step)));\n}\n\nfunction decimatedClamp(val: number, min: number, max: number, step?: number) {\n if (step == null || step <= 0) {\n return clamp(val, min, max);\n }\n const roundedValue = roundValueToStep(val, step, min);\n return clamp(roundedValue, min, max);\n}\n\nexport function rescale(\n value: number,\n from: [number, number],\n to: [number, number],\n options: { step?: number } = {},\n) {\n const scaled = ((value - from[0]) / (from[1] - from[0])) * (to[1] - to[0]) + to[0];\n return decimatedClamp(scaled, to[0], to[1], options.step);\n}\n"],"names":["clamp","value","min","max","Math","precisionRound","number","precision","factor","pow","round","getDecimalPrecision","num","abs","parts","toExponential","split","matissaDecimalPart","length","parseInt","decimalPart","toString","roundValueToStep","step","nearest","Number","toFixed","decimatedClamp","val","roundedValue","rescale","from","to","options","scaled"],"mappings":"AAAA,OAAO,MAAMA,QAAQ,CAACC,OAAeC,KAAaC,MAChDC,KAAKD,GAAG,CAACD,KAAKE,KAAKF,GAAG,CAACD,OAAOE,MAAM;AAEtC,OAAO,SAASE,eAAeC,MAAc,EAAEC,YAAY,CAAC;IAC1D,IAAIC,SAASJ,KAAKK,GAAG,CAAC,IAAIF;IAC1B,OAAOH,KAAKM,KAAK,CAACJ,SAASE,UAAUA;AACvC;AAEA;;;CAGC,GACD,SAASG,oBAAoBC,GAAW;IACtC,0FAA0F;IAC1F,kGAAkG;IAClG,IAAIR,KAAKS,GAAG,CAACD,OAAO,GAAG;QACrB,MAAME,QAAQF,IAAIG,aAAa,GAAGC,KAAK,CAAC;QACxC,MAAMC,qBAAqBH,KAAK,CAAC,EAAE,CAACE,KAAK,CAAC,IAAI,CAAC,EAAE;QACjD,OAAO,AAACC,CAAAA,qBAAqBA,mBAAmBC,MAAM,GAAG,CAAA,IAAKC,SAASL,KAAK,CAAC,EAAE,EAAE;IACnF;IAEA,MAAMM,cAAcR,IAAIS,QAAQ,GAAGL,KAAK,CAAC,IAAI,CAAC,EAAE;IAChD,OAAOI,cAAcA,YAAYF,MAAM,GAAG;AAC5C;AAEA,SAASI,iBAAiBrB,KAAa,EAAEsB,IAAY,EAAErB,GAAW;IAChE,MAAMsB,UAAUpB,KAAKM,KAAK,CAAC,AAACT,CAAAA,QAAQC,GAAE,IAAKqB,QAAQA,OAAOrB;IAC1D,OAAOuB,OAAOD,QAAQE,OAAO,CAACf,oBAAoBY;AACpD;AAEA,SAASI,eAAeC,GAAW,EAAE1B,GAAW,EAAEC,GAAW,EAAEoB,IAAa;IAC1E,IAAIA,QAAQ,QAAQA,QAAQ,GAAG;QAC7B,OAAOvB,MAAM4B,KAAK1B,KAAKC;IACzB;IACA,MAAM0B,eAAeP,iBAAiBM,KAAKL,MAAMrB;IACjD,OAAOF,MAAM6B,cAAc3B,KAAKC;AAClC;AAEA,OAAO,SAAS2B,QACd7B,KAAa,EACb8B,IAAsB,EACtBC,EAAoB,EACpBC,UAA6B,CAAC,CAAC;IAE/B,MAAMC,SAAS,AAAEjC,CAAAA,QAAQ8B,IAAI,CAAC,EAAE,AAAD,IAAMA,CAAAA,IAAI,CAAC,EAAE,GAAGA,IAAI,CAAC,EAAE,AAAD,IAAOC,CAAAA,EAAE,CAAC,EAAE,GAAGA,EAAE,CAAC,EAAE,AAAD,IAAKA,EAAE,CAAC,EAAE;IAClF,OAAOL,eAAeO,QAAQF,EAAE,CAAC,EAAE,EAAEA,EAAE,CAAC,EAAE,EAAEC,QAAQV,IAAI;AAC1D"}
|
package/dist/helpers/math.js
CHANGED
|
@@ -6,19 +6,30 @@ export function precisionRound(number) {
|
|
|
6
6
|
var factor = Math.pow(10, precision);
|
|
7
7
|
return Math.round(number * factor) / factor;
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Решение скопировано без изменений у MUI:
|
|
11
|
+
* https://github.com/mui/material-ui/blob/v5.13.7/packages/mui-base/src/useSlider/useSlider.ts#L89-L105
|
|
12
|
+
*/ function getDecimalPrecision(num) {
|
|
13
|
+
// This handles the case when num is very small (0.00000001), js will turn this into 1e-8.
|
|
14
|
+
// When num is bigger than 1 or less than -1 it won't get converted to this notation so it's fine.
|
|
15
|
+
if (Math.abs(num) < 1) {
|
|
16
|
+
var parts = num.toExponential().split("e-");
|
|
17
|
+
var matissaDecimalPart = parts[0].split(".")[1];
|
|
18
|
+
return (matissaDecimalPart ? matissaDecimalPart.length : 0) + parseInt(parts[1], 10);
|
|
19
|
+
}
|
|
20
|
+
var decimalPart = num.toString().split(".")[1];
|
|
21
|
+
return decimalPart ? decimalPart.length : 0;
|
|
22
|
+
}
|
|
23
|
+
function roundValueToStep(value, step, min) {
|
|
24
|
+
var nearest = Math.round((value - min) / step) * step + min;
|
|
25
|
+
return Number(nearest.toFixed(getDecimalPrecision(step)));
|
|
11
26
|
}
|
|
12
27
|
function decimatedClamp(val, min, max, step) {
|
|
13
28
|
if (step == null || step <= 0) {
|
|
14
29
|
return clamp(val, min, max);
|
|
15
30
|
}
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
var decimatedOffset = precisionRound(Math.round((val - min) / step) * step, prec);
|
|
19
|
-
// Round range length _down_ to nearest min + k2 * step
|
|
20
|
-
var decimatedRange = precisionRound(Math.floor((max - min) / step) * step, prec);
|
|
21
|
-
return min + clamp(decimatedOffset, 0, decimatedRange);
|
|
31
|
+
var roundedValue = roundValueToStep(val, step, min);
|
|
32
|
+
return clamp(roundedValue, min, max);
|
|
22
33
|
}
|
|
23
34
|
export function rescale(value, from, to) {
|
|
24
35
|
var options = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : {};
|
package/dist/helpers/math.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/helpers/math.ts"],"sourcesContent":["export const clamp = (value: number, min: number, max: number) =>\n Math.max(min, Math.min(value, max));\n\nexport function precisionRound(number: number, precision = 1) {\n let factor = Math.pow(10, precision);\n return Math.round(number * factor) / factor;\n}\n\nfunction
|
|
1
|
+
{"version":3,"sources":["../../src/helpers/math.ts"],"sourcesContent":["export const clamp = (value: number, min: number, max: number) =>\n Math.max(min, Math.min(value, max));\n\nexport function precisionRound(number: number, precision = 1) {\n let factor = Math.pow(10, precision);\n return Math.round(number * factor) / factor;\n}\n\n/**\n * Решение скопировано без изменений у MUI:\n * https://github.com/mui/material-ui/blob/v5.13.7/packages/mui-base/src/useSlider/useSlider.ts#L89-L105\n */\nfunction getDecimalPrecision(num: number) {\n // This handles the case when num is very small (0.00000001), js will turn this into 1e-8.\n // When num is bigger than 1 or less than -1 it won't get converted to this notation so it's fine.\n if (Math.abs(num) < 1) {\n const parts = num.toExponential().split('e-');\n const matissaDecimalPart = parts[0].split('.')[1];\n return (matissaDecimalPart ? matissaDecimalPart.length : 0) + parseInt(parts[1], 10);\n }\n\n const decimalPart = num.toString().split('.')[1];\n return decimalPart ? decimalPart.length : 0;\n}\n\nfunction roundValueToStep(value: number, step: number, min: number) {\n const nearest = Math.round((value - min) / step) * step + min;\n return Number(nearest.toFixed(getDecimalPrecision(step)));\n}\n\nfunction decimatedClamp(val: number, min: number, max: number, step?: number) {\n if (step == null || step <= 0) {\n return clamp(val, min, max);\n }\n const roundedValue = roundValueToStep(val, step, min);\n return clamp(roundedValue, min, max);\n}\n\nexport function rescale(\n value: number,\n from: [number, number],\n to: [number, number],\n options: { step?: number } = {},\n) {\n const scaled = ((value - from[0]) / (from[1] - from[0])) * (to[1] - to[0]) + to[0];\n return decimatedClamp(scaled, to[0], to[1], options.step);\n}\n"],"names":["clamp","value","min","max","Math","precisionRound","number","precision","factor","pow","round","getDecimalPrecision","num","abs","parts","toExponential","split","matissaDecimalPart","length","parseInt","decimalPart","toString","roundValueToStep","step","nearest","Number","toFixed","decimatedClamp","val","roundedValue","rescale","from","to","options","scaled"],"mappings":"AAAA,OAAO,IAAMA,QAAQ,SAACC,OAAeC,KAAaC;WAChDC,KAAKD,GAAG,CAACD,KAAKE,KAAKF,GAAG,CAACD,OAAOE;EAAM;AAEtC,OAAO,SAASE,eAAeC,MAAc;QAAEC,YAAAA,iEAAY;IACzD,IAAIC,SAASJ,KAAKK,GAAG,CAAC,IAAIF;IAC1B,OAAOH,KAAKM,KAAK,CAACJ,SAASE,UAAUA;AACvC;AAEA;;;CAGC,GACD,SAASG,oBAAoBC,GAAW;IACtC,0FAA0F;IAC1F,kGAAkG;IAClG,IAAIR,KAAKS,GAAG,CAACD,OAAO,GAAG;QACrB,IAAME,QAAQF,IAAIG,aAAa,GAAGC,KAAK,CAAC;QACxC,IAAMC,qBAAqBH,KAAK,CAAC,EAAE,CAACE,KAAK,CAAC,IAAI,CAAC,EAAE;QACjD,OAAO,AAACC,CAAAA,qBAAqBA,mBAAmBC,MAAM,GAAG,CAAA,IAAKC,SAASL,KAAK,CAAC,EAAE,EAAE;IACnF;IAEA,IAAMM,cAAcR,IAAIS,QAAQ,GAAGL,KAAK,CAAC,IAAI,CAAC,EAAE;IAChD,OAAOI,cAAcA,YAAYF,MAAM,GAAG;AAC5C;AAEA,SAASI,iBAAiBrB,KAAa,EAAEsB,IAAY,EAAErB,GAAW;IAChE,IAAMsB,UAAUpB,KAAKM,KAAK,CAAC,AAACT,CAAAA,QAAQC,GAAE,IAAKqB,QAAQA,OAAOrB;IAC1D,OAAOuB,OAAOD,QAAQE,OAAO,CAACf,oBAAoBY;AACpD;AAEA,SAASI,eAAeC,GAAW,EAAE1B,GAAW,EAAEC,GAAW,EAAEoB,IAAa;IAC1E,IAAIA,QAAQ,QAAQA,QAAQ,GAAG;QAC7B,OAAOvB,MAAM4B,KAAK1B,KAAKC;IACzB;IACA,IAAM0B,eAAeP,iBAAiBM,KAAKL,MAAMrB;IACjD,OAAOF,MAAM6B,cAAc3B,KAAKC;AAClC;AAEA,OAAO,SAAS2B,QACd7B,KAAa,EACb8B,IAAsB,EACtBC,EAAoB;QACpBC,UAAAA,iEAA6B,CAAC;IAE9B,IAAMC,SAAS,AAAEjC,CAAAA,QAAQ8B,IAAI,CAAC,EAAE,AAAD,IAAMA,CAAAA,IAAI,CAAC,EAAE,GAAGA,IAAI,CAAC,EAAE,AAAD,IAAOC,CAAAA,EAAE,CAAC,EAAE,GAAGA,EAAE,CAAC,EAAE,AAAD,IAAKA,EAAE,CAAC,EAAE;IAClF,OAAOL,eAAeO,QAAQF,EAAE,CAAC,EAAE,EAAEA,EAAE,CAAC,EAAE,EAAEC,QAAQV,IAAI;AAC1D"}
|