@cloud-ru/ds-fields 1.0.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/CHANGELOG.md +8 -0
- package/LICENSE +201 -0
- package/README.md +888 -0
- package/dist/cjs/components/FieldColor/FieldColor.d.ts +48 -0
- package/dist/cjs/components/FieldColor/FieldColor.js +147 -0
- package/dist/cjs/components/FieldColor/index.d.ts +1 -0
- package/dist/cjs/components/FieldColor/index.js +17 -0
- package/dist/cjs/components/FieldColor/styles.module.css +79 -0
- package/dist/cjs/components/FieldColor/utils.d.ts +7 -0
- package/dist/cjs/components/FieldColor/utils.js +19 -0
- package/dist/cjs/components/FieldCombo/FieldCombo.d.ts +91 -0
- package/dist/cjs/components/FieldCombo/FieldCombo.js +200 -0
- package/dist/cjs/components/FieldCombo/index.d.ts +1 -0
- package/dist/cjs/components/FieldCombo/index.js +17 -0
- package/dist/cjs/components/FieldDate/FieldDate.d.ts +2 -0
- package/dist/cjs/components/FieldDate/FieldDate.js +369 -0
- package/dist/cjs/components/FieldDate/constants.d.ts +10 -0
- package/dist/cjs/components/FieldDate/constants.js +13 -0
- package/dist/cjs/components/FieldDate/index.d.ts +3 -0
- package/dist/cjs/components/FieldDate/index.js +19 -0
- package/dist/cjs/components/FieldDate/mask.d.ts +20 -0
- package/dist/cjs/components/FieldDate/mask.js +117 -0
- package/dist/cjs/components/FieldDate/styles.module.css +43 -0
- package/dist/cjs/components/FieldDate/types.d.ts +100 -0
- package/dist/cjs/components/FieldDate/types.js +2 -0
- package/dist/cjs/components/FieldDate/utils.d.ts +3 -0
- package/dist/cjs/components/FieldDate/utils.js +8 -0
- package/dist/cjs/components/FieldSecure/FieldSecure.d.ts +64 -0
- package/dist/cjs/components/FieldSecure/FieldSecure.js +158 -0
- package/dist/cjs/components/FieldSecure/index.d.ts +1 -0
- package/dist/cjs/components/FieldSecure/index.js +17 -0
- package/dist/cjs/components/FieldSelect/FieldSelect.d.ts +2 -0
- package/dist/cjs/components/FieldSelect/FieldSelect.js +360 -0
- package/dist/cjs/components/FieldSelect/constants.d.ts +4 -0
- package/dist/cjs/components/FieldSelect/constants.js +7 -0
- package/dist/cjs/components/FieldSelect/index.d.ts +3 -0
- package/dist/cjs/components/FieldSelect/index.js +19 -0
- package/dist/cjs/components/FieldSelect/styles.module.css +92 -0
- package/dist/cjs/components/FieldSelect/types.d.ts +197 -0
- package/dist/cjs/components/FieldSelect/types.js +2 -0
- package/dist/cjs/components/FieldSelect/utils.d.ts +19 -0
- package/dist/cjs/components/FieldSelect/utils.js +104 -0
- package/dist/cjs/components/FieldSlider/FieldSlider.d.ts +92 -0
- package/dist/cjs/components/FieldSlider/FieldSlider.js +196 -0
- package/dist/cjs/components/FieldSlider/index.d.ts +2 -0
- package/dist/cjs/components/FieldSlider/index.js +18 -0
- package/dist/cjs/components/FieldSlider/styles.module.css +44 -0
- package/dist/cjs/components/FieldSlider/types.d.ts +4 -0
- package/dist/cjs/components/FieldSlider/types.js +2 -0
- package/dist/cjs/components/FieldSlider/utils/generateAllowedValues.d.ts +1 -0
- package/dist/cjs/components/FieldSlider/utils/generateAllowedValues.js +16 -0
- package/dist/cjs/components/FieldSlider/utils/getClosestMark.d.ts +4 -0
- package/dist/cjs/components/FieldSlider/utils/getClosestMark.js +16 -0
- package/dist/cjs/components/FieldSlider/utils/getMarkLabel.d.ts +2 -0
- package/dist/cjs/components/FieldSlider/utils/getMarkLabel.js +7 -0
- package/dist/cjs/components/FieldSlider/utils/getTextFieldValue.d.ts +2 -0
- package/dist/cjs/components/FieldSlider/utils/getTextFieldValue.js +9 -0
- package/dist/cjs/components/FieldSlider/utils/index.d.ts +5 -0
- package/dist/cjs/components/FieldSlider/utils/index.js +21 -0
- package/dist/cjs/components/FieldSlider/utils/isMarkObject.d.ts +6 -0
- package/dist/cjs/components/FieldSlider/utils/isMarkObject.js +6 -0
- package/dist/cjs/components/FieldStepper/FieldStepper.d.ts +81 -0
- package/dist/cjs/components/FieldStepper/FieldStepper.js +160 -0
- package/dist/cjs/components/FieldStepper/index.d.ts +1 -0
- package/dist/cjs/components/FieldStepper/index.js +17 -0
- package/dist/cjs/components/FieldStepper/styles.module.css +78 -0
- package/dist/cjs/components/FieldStepper/utils.d.ts +14 -0
- package/dist/cjs/components/FieldStepper/utils.js +45 -0
- package/dist/cjs/components/FieldText/FieldText.d.ts +11 -0
- package/dist/cjs/components/FieldText/FieldText.js +14 -0
- package/dist/cjs/components/FieldText/index.d.ts +1 -0
- package/dist/cjs/components/FieldText/index.js +17 -0
- package/dist/cjs/components/FieldTextArea/FieldTextArea.d.ts +95 -0
- package/dist/cjs/components/FieldTextArea/FieldTextArea.js +114 -0
- package/dist/cjs/components/FieldTextArea/index.d.ts +1 -0
- package/dist/cjs/components/FieldTextArea/index.js +17 -0
- package/dist/cjs/components/FieldTextArea/styles.module.css +123 -0
- package/dist/cjs/components/FieldTime/FieldTime.d.ts +74 -0
- package/dist/cjs/components/FieldTime/FieldTime.js +167 -0
- package/dist/cjs/components/FieldTime/index.d.ts +2 -0
- package/dist/cjs/components/FieldTime/index.js +17 -0
- package/dist/cjs/components/FieldTime/mask.d.ts +3 -0
- package/dist/cjs/components/FieldTime/mask.js +24 -0
- package/dist/cjs/components/FieldTime/styles.module.css +3 -0
- package/dist/cjs/components/index.d.ts +14 -0
- package/dist/cjs/components/index.js +32 -0
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/FieldElementButton.d.ts +35 -0
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/FieldElementButton.js +47 -0
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/FieldElementButtonList.d.ts +26 -0
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/FieldElementButtonList.js +24 -0
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/constants.d.ts +9 -0
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/constants.js +12 -0
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/index.d.ts +4 -0
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/index.js +20 -0
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/styles.module.css +204 -0
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/types.d.ts +4 -0
- package/dist/cjs/components/shared/helperComponents/FieldElementButton/types.js +2 -0
- package/dist/cjs/components/shared/helperComponents/FieldShell/FieldShell.d.ts +43 -0
- package/dist/cjs/components/shared/helperComponents/FieldShell/FieldShell.js +22 -0
- package/dist/cjs/components/shared/helperComponents/FieldShell/index.d.ts +1 -0
- package/dist/cjs/components/shared/helperComponents/FieldShell/index.js +17 -0
- package/dist/cjs/components/shared/helperComponents/FieldShell/styles.module.css +11 -0
- package/dist/cjs/components/shared/hooks/useCopyButton.d.ts +20 -0
- package/dist/cjs/components/shared/hooks/useCopyButton.js +58 -0
- package/dist/cjs/components/shared/index.d.ts +4 -0
- package/dist/cjs/components/shared/index.js +20 -0
- package/dist/cjs/components/shared/styles.module.css +673 -0
- package/dist/cjs/components/shared/utils.d.ts +69 -0
- package/dist/cjs/components/shared/utils.js +104 -0
- package/dist/cjs/constants.d.ts +61 -0
- package/dist/cjs/constants.js +76 -0
- package/dist/cjs/hooks/index.d.ts +1 -0
- package/dist/cjs/hooks/index.js +17 -0
- package/dist/cjs/hooks/useAdaptiveAutoFocus.d.ts +7 -0
- package/dist/cjs/hooks/useAdaptiveAutoFocus.js +10 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.js +19 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/segments/index.d.ts +2 -0
- package/dist/cjs/segments/index.js +18 -0
- package/dist/cjs/segments/segments.d.ts +22 -0
- package/dist/cjs/segments/segments.js +46 -0
- package/dist/cjs/segments/useSegmentedMask.d.ts +43 -0
- package/dist/cjs/segments/useSegmentedMask.js +282 -0
- package/dist/cjs/style.css +1350 -0
- package/dist/esm/components/FieldColor/FieldColor.d.ts +48 -0
- package/dist/esm/components/FieldColor/FieldColor.js +141 -0
- package/dist/esm/components/FieldColor/index.d.ts +1 -0
- package/dist/esm/components/FieldColor/index.js +1 -0
- package/dist/esm/components/FieldColor/styles.module.css +79 -0
- package/dist/esm/components/FieldColor/utils.d.ts +7 -0
- package/dist/esm/components/FieldColor/utils.js +16 -0
- package/dist/esm/components/FieldCombo/FieldCombo.d.ts +91 -0
- package/dist/esm/components/FieldCombo/FieldCombo.js +194 -0
- package/dist/esm/components/FieldCombo/index.d.ts +1 -0
- package/dist/esm/components/FieldCombo/index.js +1 -0
- package/dist/esm/components/FieldDate/FieldDate.d.ts +2 -0
- package/dist/esm/components/FieldDate/FieldDate.js +363 -0
- package/dist/esm/components/FieldDate/constants.d.ts +10 -0
- package/dist/esm/components/FieldDate/constants.js +10 -0
- package/dist/esm/components/FieldDate/index.d.ts +3 -0
- package/dist/esm/components/FieldDate/index.js +3 -0
- package/dist/esm/components/FieldDate/mask.d.ts +20 -0
- package/dist/esm/components/FieldDate/mask.js +111 -0
- package/dist/esm/components/FieldDate/styles.module.css +43 -0
- package/dist/esm/components/FieldDate/types.d.ts +100 -0
- package/dist/esm/components/FieldDate/types.js +1 -0
- package/dist/esm/components/FieldDate/utils.d.ts +3 -0
- package/dist/esm/components/FieldDate/utils.js +5 -0
- package/dist/esm/components/FieldSecure/FieldSecure.d.ts +64 -0
- package/dist/esm/components/FieldSecure/FieldSecure.js +152 -0
- package/dist/esm/components/FieldSecure/index.d.ts +1 -0
- package/dist/esm/components/FieldSecure/index.js +1 -0
- package/dist/esm/components/FieldSelect/FieldSelect.d.ts +2 -0
- package/dist/esm/components/FieldSelect/FieldSelect.js +354 -0
- package/dist/esm/components/FieldSelect/constants.d.ts +4 -0
- package/dist/esm/components/FieldSelect/constants.js +4 -0
- package/dist/esm/components/FieldSelect/index.d.ts +3 -0
- package/dist/esm/components/FieldSelect/index.js +3 -0
- package/dist/esm/components/FieldSelect/styles.module.css +92 -0
- package/dist/esm/components/FieldSelect/types.d.ts +197 -0
- package/dist/esm/components/FieldSelect/types.js +1 -0
- package/dist/esm/components/FieldSelect/utils.d.ts +19 -0
- package/dist/esm/components/FieldSelect/utils.js +93 -0
- package/dist/esm/components/FieldSlider/FieldSlider.d.ts +92 -0
- package/dist/esm/components/FieldSlider/FieldSlider.js +190 -0
- package/dist/esm/components/FieldSlider/index.d.ts +2 -0
- package/dist/esm/components/FieldSlider/index.js +2 -0
- package/dist/esm/components/FieldSlider/styles.module.css +44 -0
- package/dist/esm/components/FieldSlider/types.d.ts +4 -0
- package/dist/esm/components/FieldSlider/types.js +1 -0
- package/dist/esm/components/FieldSlider/utils/generateAllowedValues.d.ts +1 -0
- package/dist/esm/components/FieldSlider/utils/generateAllowedValues.js +13 -0
- package/dist/esm/components/FieldSlider/utils/getClosestMark.d.ts +4 -0
- package/dist/esm/components/FieldSlider/utils/getClosestMark.js +13 -0
- package/dist/esm/components/FieldSlider/utils/getMarkLabel.d.ts +2 -0
- package/dist/esm/components/FieldSlider/utils/getMarkLabel.js +4 -0
- package/dist/esm/components/FieldSlider/utils/getTextFieldValue.d.ts +2 -0
- package/dist/esm/components/FieldSlider/utils/getTextFieldValue.js +6 -0
- package/dist/esm/components/FieldSlider/utils/index.d.ts +5 -0
- package/dist/esm/components/FieldSlider/utils/index.js +5 -0
- package/dist/esm/components/FieldSlider/utils/isMarkObject.d.ts +6 -0
- package/dist/esm/components/FieldSlider/utils/isMarkObject.js +3 -0
- package/dist/esm/components/FieldStepper/FieldStepper.d.ts +81 -0
- package/dist/esm/components/FieldStepper/FieldStepper.js +154 -0
- package/dist/esm/components/FieldStepper/index.d.ts +1 -0
- package/dist/esm/components/FieldStepper/index.js +1 -0
- package/dist/esm/components/FieldStepper/styles.module.css +78 -0
- package/dist/esm/components/FieldStepper/utils.d.ts +14 -0
- package/dist/esm/components/FieldStepper/utils.js +38 -0
- package/dist/esm/components/FieldText/FieldText.d.ts +11 -0
- package/dist/esm/components/FieldText/FieldText.js +11 -0
- package/dist/esm/components/FieldText/index.d.ts +1 -0
- package/dist/esm/components/FieldText/index.js +1 -0
- package/dist/esm/components/FieldTextArea/FieldTextArea.d.ts +95 -0
- package/dist/esm/components/FieldTextArea/FieldTextArea.js +108 -0
- package/dist/esm/components/FieldTextArea/index.d.ts +1 -0
- package/dist/esm/components/FieldTextArea/index.js +1 -0
- package/dist/esm/components/FieldTextArea/styles.module.css +123 -0
- package/dist/esm/components/FieldTime/FieldTime.d.ts +74 -0
- package/dist/esm/components/FieldTime/FieldTime.js +161 -0
- package/dist/esm/components/FieldTime/index.d.ts +2 -0
- package/dist/esm/components/FieldTime/index.js +1 -0
- package/dist/esm/components/FieldTime/mask.d.ts +3 -0
- package/dist/esm/components/FieldTime/mask.js +20 -0
- package/dist/esm/components/FieldTime/styles.module.css +3 -0
- package/dist/esm/components/index.d.ts +14 -0
- package/dist/esm/components/index.js +12 -0
- package/dist/esm/components/shared/helperComponents/FieldElementButton/FieldElementButton.d.ts +35 -0
- package/dist/esm/components/shared/helperComponents/FieldElementButton/FieldElementButton.js +41 -0
- package/dist/esm/components/shared/helperComponents/FieldElementButton/FieldElementButtonList.d.ts +26 -0
- package/dist/esm/components/shared/helperComponents/FieldElementButton/FieldElementButtonList.js +21 -0
- package/dist/esm/components/shared/helperComponents/FieldElementButton/constants.d.ts +9 -0
- package/dist/esm/components/shared/helperComponents/FieldElementButton/constants.js +9 -0
- package/dist/esm/components/shared/helperComponents/FieldElementButton/index.d.ts +4 -0
- package/dist/esm/components/shared/helperComponents/FieldElementButton/index.js +4 -0
- package/dist/esm/components/shared/helperComponents/FieldElementButton/styles.module.css +204 -0
- package/dist/esm/components/shared/helperComponents/FieldElementButton/types.d.ts +4 -0
- package/dist/esm/components/shared/helperComponents/FieldElementButton/types.js +1 -0
- package/dist/esm/components/shared/helperComponents/FieldShell/FieldShell.d.ts +43 -0
- package/dist/esm/components/shared/helperComponents/FieldShell/FieldShell.js +16 -0
- package/dist/esm/components/shared/helperComponents/FieldShell/index.d.ts +1 -0
- package/dist/esm/components/shared/helperComponents/FieldShell/index.js +1 -0
- package/dist/esm/components/shared/helperComponents/FieldShell/styles.module.css +11 -0
- package/dist/esm/components/shared/hooks/useCopyButton.d.ts +20 -0
- package/dist/esm/components/shared/hooks/useCopyButton.js +55 -0
- package/dist/esm/components/shared/index.d.ts +4 -0
- package/dist/esm/components/shared/index.js +4 -0
- package/dist/esm/components/shared/styles.module.css +673 -0
- package/dist/esm/components/shared/utils.d.ts +69 -0
- package/dist/esm/components/shared/utils.js +91 -0
- package/dist/esm/constants.d.ts +61 -0
- package/dist/esm/constants.js +73 -0
- package/dist/esm/hooks/index.d.ts +1 -0
- package/dist/esm/hooks/index.js +1 -0
- package/dist/esm/hooks/useAdaptiveAutoFocus.d.ts +7 -0
- package/dist/esm/hooks/useAdaptiveAutoFocus.js +7 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/segments/index.d.ts +2 -0
- package/dist/esm/segments/index.js +2 -0
- package/dist/esm/segments/segments.d.ts +22 -0
- package/dist/esm/segments/segments.js +43 -0
- package/dist/esm/segments/useSegmentedMask.d.ts +43 -0
- package/dist/esm/segments/useSegmentedMask.js +279 -0
- package/dist/esm/style.css +1350 -0
- package/dist/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/package.json +62 -0
- package/src/components/FieldColor/FieldColor.tsx +426 -0
- package/src/components/FieldColor/index.ts +1 -0
- package/src/components/FieldColor/styles.module.scss +120 -0
- package/src/components/FieldColor/utils.ts +17 -0
- package/src/components/FieldCombo/FieldCombo.tsx +495 -0
- package/src/components/FieldCombo/index.ts +1 -0
- package/src/components/FieldDate/FieldDate.tsx +658 -0
- package/src/components/FieldDate/constants.ts +11 -0
- package/src/components/FieldDate/index.ts +3 -0
- package/src/components/FieldDate/mask.ts +123 -0
- package/src/components/FieldDate/styles.module.scss +56 -0
- package/src/components/FieldDate/types.ts +124 -0
- package/src/components/FieldDate/utils.ts +7 -0
- package/src/components/FieldSecure/FieldSecure.tsx +398 -0
- package/src/components/FieldSecure/index.ts +1 -0
- package/src/components/FieldSelect/FieldSelect.tsx +689 -0
- package/src/components/FieldSelect/constants.ts +4 -0
- package/src/components/FieldSelect/index.ts +3 -0
- package/src/components/FieldSelect/styles.module.scss +104 -0
- package/src/components/FieldSelect/types.ts +212 -0
- package/src/components/FieldSelect/utils.ts +134 -0
- package/src/components/FieldSlider/FieldSlider.tsx +502 -0
- package/src/components/FieldSlider/index.ts +2 -0
- package/src/components/FieldSlider/styles.module.scss +47 -0
- package/src/components/FieldSlider/types.ts +5 -0
- package/src/components/FieldSlider/utils/generateAllowedValues.ts +13 -0
- package/src/components/FieldSlider/utils/getClosestMark.ts +21 -0
- package/src/components/FieldSlider/utils/getMarkLabel.ts +7 -0
- package/src/components/FieldSlider/utils/getTextFieldValue.ts +8 -0
- package/src/components/FieldSlider/utils/index.ts +5 -0
- package/src/components/FieldSlider/utils/isMarkObject.ts +7 -0
- package/src/components/FieldStepper/FieldStepper.tsx +457 -0
- package/src/components/FieldStepper/index.ts +1 -0
- package/src/components/FieldStepper/styles.module.scss +98 -0
- package/src/components/FieldStepper/utils.ts +44 -0
- package/src/components/FieldText/FieldText.tsx +27 -0
- package/src/components/FieldText/index.ts +1 -0
- package/src/components/FieldTextArea/FieldTextArea.tsx +374 -0
- package/src/components/FieldTextArea/index.ts +1 -0
- package/src/components/FieldTextArea/styles.module.scss +192 -0
- package/src/components/FieldTime/FieldTime.tsx +401 -0
- package/src/components/FieldTime/index.ts +2 -0
- package/src/components/FieldTime/mask.ts +22 -0
- package/src/components/FieldTime/styles.module.scss +3 -0
- package/src/components/index.ts +14 -0
- package/src/components/shared/helperComponents/FieldElementButton/FieldElementButton.tsx +127 -0
- package/src/components/shared/helperComponents/FieldElementButton/FieldElementButtonList.tsx +72 -0
- package/src/components/shared/helperComponents/FieldElementButton/constants.ts +10 -0
- package/src/components/shared/helperComponents/FieldElementButton/index.ts +4 -0
- package/src/components/shared/helperComponents/FieldElementButton/styles.module.scss +137 -0
- package/src/components/shared/helperComponents/FieldElementButton/types.ts +6 -0
- package/src/components/shared/helperComponents/FieldShell/FieldShell.tsx +100 -0
- package/src/components/shared/helperComponents/FieldShell/index.ts +1 -0
- package/src/components/shared/helperComponents/FieldShell/styles.module.scss +13 -0
- package/src/components/shared/hooks/useCopyButton.tsx +103 -0
- package/src/components/shared/index.ts +4 -0
- package/src/components/shared/styles.module.scss +409 -0
- package/src/components/shared/utils.ts +128 -0
- package/src/constants.ts +73 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useAdaptiveAutoFocus.ts +16 -0
- package/src/index.ts +3 -0
- package/src/segments/index.ts +2 -0
- package/src/segments/segments.ts +74 -0
- package/src/segments/useSegmentedMask.ts +361 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { FieldDecoratorProps, ValidationState } from '@cloud-ru/ds-field-decorator';
|
|
2
|
+
import { DroplistProps, ItemId, ItemProps } from '@cloud-ru/ds-list';
|
|
3
|
+
import { ValueOf } from '@cloud-ru/ds-utils';
|
|
4
|
+
import { FocusEvent, KeyboardEvent, ReactNode } from 'react';
|
|
5
|
+
import { FieldLayoutPresets } from '../../hooks';
|
|
6
|
+
import { SELECTION_MODE } from './constants';
|
|
7
|
+
/** Режим выбора FieldSelect: одно значение или несколько. */
|
|
8
|
+
export type Selection = ValueOf<typeof SELECTION_MODE>;
|
|
9
|
+
type FieldSelectDecoratorProps = Omit<FieldDecoratorProps, 'children' | 'validationState' | 'size'>;
|
|
10
|
+
type DroplistPassthrough = Pick<DroplistProps, 'footer' | 'footerActiveElementsRefs' | 'loading' | 'noDataState' | 'noResultsState' | 'errorDataState' | 'virtualized' | 'scrollToSelectedItem' | 'limitedScrollHeight' | 'untouchableScrollbars' | 'closeOnPopstate'> & {
|
|
11
|
+
/**
|
|
12
|
+
* Флаг «ошибка загрузки данных» — при `true` дроплист рендерит `errorDataState`
|
|
13
|
+
* вместо списка (для асинхронной подгрузки с провалившимся запросом).
|
|
14
|
+
*/
|
|
15
|
+
dataError?: DroplistProps['dataError'];
|
|
16
|
+
/**
|
|
17
|
+
* Флаг «список отфильтрован» — при `true` и пустом результате дроплист рендерит
|
|
18
|
+
* `noResultsState`. По умолчанию выводится из строки поиска (`searchable` + ввод).
|
|
19
|
+
*/
|
|
20
|
+
dataFiltered?: DroplistProps['dataFiltered'];
|
|
21
|
+
};
|
|
22
|
+
type CommonSelectProps = FieldSelectDecoratorProps & DroplistPassthrough & {
|
|
23
|
+
/** Размер */
|
|
24
|
+
size?: FieldDecoratorProps['size'];
|
|
25
|
+
/** Состояние валидации */
|
|
26
|
+
validationState?: ValidationState;
|
|
27
|
+
/** CSS-класс корня `FieldDecorator` */
|
|
28
|
+
className?: string;
|
|
29
|
+
/** CSS-класс оболочки поля */
|
|
30
|
+
fieldClassName?: string;
|
|
31
|
+
/** Список айтемов дроплиста (формат `@cloud-ru/ds-list`) */
|
|
32
|
+
items: ItemProps[];
|
|
33
|
+
/** Пресет-айтемы сверху (формат `@cloud-ru/ds-list`) */
|
|
34
|
+
pinTop?: ItemProps[];
|
|
35
|
+
/** Пресет-айтемы снизу (формат `@cloud-ru/ds-list`) */
|
|
36
|
+
pinBottom?: ItemProps[];
|
|
37
|
+
/** Placeholder в триггере, когда нет выбранного значения */
|
|
38
|
+
placeholder?: string;
|
|
39
|
+
/** Иконка перед текстом */
|
|
40
|
+
iconBefore?: ReactNode;
|
|
41
|
+
/** Префикс — текст или нода перед значением (Figma `prefix`) */
|
|
42
|
+
prefix?: ReactNode;
|
|
43
|
+
/** Постфикс — текст или нода после значения (Figma `postfix`) */
|
|
44
|
+
postfix?: ReactNode;
|
|
45
|
+
/** Деактивировано */
|
|
46
|
+
disabled?: boolean;
|
|
47
|
+
/** Read-only режим */
|
|
48
|
+
readonly?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Фон поля (acrylic)
|
|
51
|
+
* @default true
|
|
52
|
+
*/
|
|
53
|
+
background?: boolean;
|
|
54
|
+
/** Управляемое открытие дроплиста */
|
|
55
|
+
open?: DroplistProps['open'];
|
|
56
|
+
/** Колбек смены открытия */
|
|
57
|
+
onOpenChange?: DroplistProps['onOpenChange'];
|
|
58
|
+
/** Placement дроплиста */
|
|
59
|
+
placement?: DroplistProps['placement'];
|
|
60
|
+
/**
|
|
61
|
+
* Стратегия ширины дроплиста.
|
|
62
|
+
* @default 'eq' — равна ширине триггера
|
|
63
|
+
*/
|
|
64
|
+
widthStrategy?: DroplistProps['widthStrategy'];
|
|
65
|
+
/**
|
|
66
|
+
* Включить поиск/ввод в поле — пользователь печатает, список фильтруется по подстроке лейбла.
|
|
67
|
+
* @default true
|
|
68
|
+
*/
|
|
69
|
+
searchable?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Управляемое/неуправляемое состояние строки поиска (текста в поле). Позволяет потребителю
|
|
72
|
+
* читать и задавать запрос (например, для серверного поиска вместе с `autocomplete`).
|
|
73
|
+
*/
|
|
74
|
+
search?: {
|
|
75
|
+
/** Управляемое значение строки поиска */
|
|
76
|
+
value?: string;
|
|
77
|
+
/** Начальное значение строки поиска (uncontrolled) */
|
|
78
|
+
defaultValue?: string;
|
|
79
|
+
/** Колбек смены строки поиска */
|
|
80
|
+
onChange?(value: string): void;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Не фильтровать список на клиенте — фильтрацию обеспечивает потребитель (серверный поиск).
|
|
84
|
+
* Введённый текст уходит в `search.onChange`, список берётся из `items` как есть.
|
|
85
|
+
* @default false
|
|
86
|
+
*/
|
|
87
|
+
autocomplete?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Зафиксировать введённый текст как новый выбор по `Enter` (создание опции «на лету»).
|
|
90
|
+
* @default false
|
|
91
|
+
*/
|
|
92
|
+
addOptionByEnter?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Сбрасывать строку поиска к выбранному значению после выбора. `false` нужен при асинхронной
|
|
95
|
+
* подгрузке (оставить введённый запрос как значение, пока данные не пришли).
|
|
96
|
+
* @default true
|
|
97
|
+
*/
|
|
98
|
+
resetSearchOnOptionSelection?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Показывать кнопку очистки значения (✕). Активна, когда есть выбранное значение
|
|
101
|
+
* и поле не disabled/readonly.
|
|
102
|
+
* @default true
|
|
103
|
+
*/
|
|
104
|
+
showClearButton?: boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Показывать кнопку копирования значения (только при `readonly` и непустом значении).
|
|
107
|
+
* @default true
|
|
108
|
+
*/
|
|
109
|
+
showCopyButton?: boolean;
|
|
110
|
+
/** Колбек после копирования значения в буфер */
|
|
111
|
+
onCopyButtonClick?(): void;
|
|
112
|
+
/** HTML-атрибут `id` для input (и `for` у label) */
|
|
113
|
+
id?: string;
|
|
114
|
+
/** HTML-атрибут `name` для input */
|
|
115
|
+
name?: string;
|
|
116
|
+
/** Автофокус input при монтировании. На mobile выключается адаптивно (см. `layoutPresets`) */
|
|
117
|
+
autoFocus?: boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен
|
|
120
|
+
* (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`.
|
|
121
|
+
*/
|
|
122
|
+
layoutPresets?: FieldLayoutPresets;
|
|
123
|
+
/** Колбек фокуса input */
|
|
124
|
+
onFocus?(event: FocusEvent<HTMLInputElement>): void;
|
|
125
|
+
/** Колбек блюра input */
|
|
126
|
+
onBlur?(event: FocusEvent<HTMLInputElement>): void;
|
|
127
|
+
/** Колбек нажатия клавиши на input (вызывается после внутренней обработки навигации) */
|
|
128
|
+
onKeyDown?(event: KeyboardEvent<HTMLInputElement>): void;
|
|
129
|
+
/**
|
|
130
|
+
* Включить нечёткий поиск: символы запроса должны встречаться в лейбле в том же порядке
|
|
131
|
+
* (например, `lge` найдёт `Large`). Если `false` — простой substring-match.
|
|
132
|
+
* @default true
|
|
133
|
+
*/
|
|
134
|
+
enableFuzzySearch?: boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Кастомный форматтер лейбла выбранного значения. Применяется к каждому выбранному
|
|
137
|
+
* элементу (single — значение в поле, multiple — лейбл чипа или элемент в comma-joined).
|
|
138
|
+
*/
|
|
139
|
+
selectedOptionFormatter?(selected: {
|
|
140
|
+
id: ItemId;
|
|
141
|
+
label: string;
|
|
142
|
+
}): string;
|
|
143
|
+
/** Тестовый id корня */
|
|
144
|
+
'data-test-id'?: string;
|
|
145
|
+
};
|
|
146
|
+
export type FieldSelectSingleProps = CommonSelectProps & {
|
|
147
|
+
/** Режим выбора. По умолчанию `'single'`. */
|
|
148
|
+
selection?: typeof SELECTION_MODE.Single;
|
|
149
|
+
/** Управляемое значение */
|
|
150
|
+
value?: ItemId;
|
|
151
|
+
/** Неуправляемое значение по умолчанию */
|
|
152
|
+
defaultValue?: ItemId;
|
|
153
|
+
/** Колбек смены значения */
|
|
154
|
+
onChange?(value: ItemId | undefined): void;
|
|
155
|
+
/**
|
|
156
|
+
* Закрывать дроплист после клика на айтем.
|
|
157
|
+
* @default true
|
|
158
|
+
*/
|
|
159
|
+
closeDroplistOnItemClick?: boolean;
|
|
160
|
+
};
|
|
161
|
+
export type FieldSelectMultipleProps = CommonSelectProps & {
|
|
162
|
+
/** Режим выбора */
|
|
163
|
+
selection: typeof SELECTION_MODE.Multiple;
|
|
164
|
+
/** Управляемые значения */
|
|
165
|
+
value?: ItemId[];
|
|
166
|
+
/** Неуправляемые значения по умолчанию */
|
|
167
|
+
defaultValue?: ItemId[];
|
|
168
|
+
/** Колбек смены значений */
|
|
169
|
+
onChange?(value: ItemId[]): void;
|
|
170
|
+
/**
|
|
171
|
+
* Форматтер строки выбранных значений (используется, если `chips=false`).
|
|
172
|
+
* @default — список лейблов через `, `
|
|
173
|
+
*/
|
|
174
|
+
formatSelected?(selected: {
|
|
175
|
+
id: ItemId;
|
|
176
|
+
label: string;
|
|
177
|
+
}[]): string;
|
|
178
|
+
/**
|
|
179
|
+
* Отображать выбранные значения как чипы (`@cloud-ru/ds-tag`) внутри поля. Если `false`,
|
|
180
|
+
* показывает строку из `formatSelected` либо comma-joined.
|
|
181
|
+
* @default true
|
|
182
|
+
*/
|
|
183
|
+
chips?: boolean;
|
|
184
|
+
/**
|
|
185
|
+
* Удалять последний чип по `Backspace`, когда строка ввода пустая.
|
|
186
|
+
* Работает только при `chips=true` и `searchable=true`.
|
|
187
|
+
* @default true
|
|
188
|
+
*/
|
|
189
|
+
removeByBackspace?: boolean;
|
|
190
|
+
/**
|
|
191
|
+
* Закрывать дроплист после клика на айтем.
|
|
192
|
+
* @default false
|
|
193
|
+
*/
|
|
194
|
+
closeDroplistOnItemClick?: boolean;
|
|
195
|
+
};
|
|
196
|
+
export type FieldSelectProps = FieldSelectSingleProps | FieldSelectMultipleProps;
|
|
197
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Size } from '@cloud-ru/ds-field-decorator';
|
|
2
|
+
import { ItemId, ItemProps } from '@cloud-ru/ds-list';
|
|
3
|
+
import { Appearance as TagAppearance, Size as TagSize } from '@cloud-ru/ds-tag';
|
|
4
|
+
import { FieldSelectMultipleProps, FieldSelectProps } from './types';
|
|
5
|
+
export declare const TAG_SIZE_MAP: Record<Size, TagSize>;
|
|
6
|
+
export type WithIdContent = {
|
|
7
|
+
id?: ItemId;
|
|
8
|
+
content?: unknown;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
appearance?: unknown;
|
|
11
|
+
};
|
|
12
|
+
export declare function extractLabel(item: WithIdContent): string;
|
|
13
|
+
export declare function extractSearchText(item: WithIdContent): string;
|
|
14
|
+
export declare function extractAppearance(item?: WithIdContent): TagAppearance | undefined;
|
|
15
|
+
export declare function flatten(items: ItemProps[]): WithIdContent[];
|
|
16
|
+
export declare function findItem(items: ItemProps[], id: ItemId): WithIdContent | undefined;
|
|
17
|
+
export declare function isFuzzyMatch(haystack: string, needle: string): boolean;
|
|
18
|
+
export declare function filterItems(items: ItemProps[], query: string, fuzzy: boolean): ItemProps[];
|
|
19
|
+
export declare function isMultiple(props: FieldSelectProps): props is FieldSelectMultipleProps;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TAG_SIZE_MAP = void 0;
|
|
4
|
+
exports.extractLabel = extractLabel;
|
|
5
|
+
exports.extractSearchText = extractSearchText;
|
|
6
|
+
exports.extractAppearance = extractAppearance;
|
|
7
|
+
exports.flatten = flatten;
|
|
8
|
+
exports.findItem = findItem;
|
|
9
|
+
exports.isFuzzyMatch = isFuzzyMatch;
|
|
10
|
+
exports.filterItems = filterItems;
|
|
11
|
+
exports.isMultiple = isMultiple;
|
|
12
|
+
const constants_1 = require("./constants");
|
|
13
|
+
exports.TAG_SIZE_MAP = { s: 'xs', m: 'xs', l: 's' };
|
|
14
|
+
function extractLabel(item) {
|
|
15
|
+
const { content, id } = item;
|
|
16
|
+
if (!content) {
|
|
17
|
+
return String(id ?? '');
|
|
18
|
+
}
|
|
19
|
+
if (typeof content === 'string' || typeof content === 'number') {
|
|
20
|
+
return String(content);
|
|
21
|
+
}
|
|
22
|
+
if (typeof content === 'object' && content !== null && 'label' in content) {
|
|
23
|
+
return String(content.label);
|
|
24
|
+
}
|
|
25
|
+
return String(id ?? '');
|
|
26
|
+
}
|
|
27
|
+
// Текст для поиска: лейбл (option) + caption + description — паритет с легаси `useSearch`,
|
|
28
|
+
// который матчил запрос по всем трём полям контента, а не только по лейблу.
|
|
29
|
+
function extractSearchText(item) {
|
|
30
|
+
const parts = [extractLabel(item)];
|
|
31
|
+
const { content } = item;
|
|
32
|
+
if (content && typeof content === 'object') {
|
|
33
|
+
const c = content;
|
|
34
|
+
if (typeof c.caption === 'string') {
|
|
35
|
+
parts.push(c.caption);
|
|
36
|
+
}
|
|
37
|
+
if (typeof c.description === 'string') {
|
|
38
|
+
parts.push(c.description);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return parts.join(' ');
|
|
42
|
+
}
|
|
43
|
+
// Цвет чипа выбранного значения (multiple) — паритет с легаси `option.appearance`.
|
|
44
|
+
// Берётся с самого item'а (additive: потребитель задаёт `appearance` на элементе items).
|
|
45
|
+
function extractAppearance(item) {
|
|
46
|
+
const a = item?.appearance;
|
|
47
|
+
return typeof a === 'string' ? a : undefined;
|
|
48
|
+
}
|
|
49
|
+
function flatten(items) {
|
|
50
|
+
const out = [];
|
|
51
|
+
for (const item of items) {
|
|
52
|
+
out.push(item);
|
|
53
|
+
if ('items' in item && Array.isArray(item.items)) {
|
|
54
|
+
out.push(...flatten(item.items));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
function findItem(items, id) {
|
|
60
|
+
for (const item of flatten(items)) {
|
|
61
|
+
if (item.id === id) {
|
|
62
|
+
return item;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
// Subsequence-fuzzy: символы запроса должны встречаться в строке в исходном порядке.
|
|
68
|
+
// Пример: query=`lge` matches `Large` (L → r → arg → e).
|
|
69
|
+
function isFuzzyMatch(haystack, needle) {
|
|
70
|
+
if (!needle) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
let i = 0;
|
|
74
|
+
for (const ch of haystack) {
|
|
75
|
+
if (ch === needle[i]) {
|
|
76
|
+
i += 1;
|
|
77
|
+
if (i === needle.length) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
function filterItems(items, query, fuzzy) {
|
|
85
|
+
if (!query) {
|
|
86
|
+
return items;
|
|
87
|
+
}
|
|
88
|
+
const q = query.toLowerCase();
|
|
89
|
+
const matches = (item) => {
|
|
90
|
+
const text = extractSearchText(item).toLowerCase();
|
|
91
|
+
return fuzzy ? isFuzzyMatch(text, q) : text.includes(q);
|
|
92
|
+
};
|
|
93
|
+
const walk = (list) => list.flatMap(item => {
|
|
94
|
+
if ('items' in item && Array.isArray(item.items)) {
|
|
95
|
+
const filteredChildren = walk(item.items);
|
|
96
|
+
return filteredChildren.length > 0 ? [{ ...item, items: filteredChildren }] : [];
|
|
97
|
+
}
|
|
98
|
+
return matches(item) ? [item] : [];
|
|
99
|
+
});
|
|
100
|
+
return walk(items);
|
|
101
|
+
}
|
|
102
|
+
function isMultiple(props) {
|
|
103
|
+
return props.selection === constants_1.SELECTION_MODE.Multiple;
|
|
104
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { FieldDecoratorProps } from '@cloud-ru/ds-field-decorator';
|
|
2
|
+
import { SliderProps } from '@cloud-ru/ds-slider';
|
|
3
|
+
import { FocusEvent, ReactElement, ReactNode } from 'react';
|
|
4
|
+
import { FieldLayoutPresets } from '../../hooks';
|
|
5
|
+
import { SliderValue, TextInputFormatter } from './types';
|
|
6
|
+
type SliderMarks = NonNullable<SliderProps['marks']>;
|
|
7
|
+
type FieldSliderDecoratorProps = Omit<FieldDecoratorProps, 'children'>;
|
|
8
|
+
type FieldSliderOwnProps = {
|
|
9
|
+
/** CSS-класс корня `FieldDecorator` */
|
|
10
|
+
className?: string;
|
|
11
|
+
/** CSS-класс оболочки поля */
|
|
12
|
+
fieldClassName?: string;
|
|
13
|
+
/** Значение (число или диапазон при `range`; controlled-режим) */
|
|
14
|
+
value?: SliderValue;
|
|
15
|
+
/** Начальное значение (uncontrolled-режим). По умолчанию `min` (или `[min, max]` при `range`). */
|
|
16
|
+
defaultValue?: SliderValue;
|
|
17
|
+
/** Колбек смены значения */
|
|
18
|
+
onChange?(value: SliderValue): void;
|
|
19
|
+
/**
|
|
20
|
+
* Диапазон с двумя ручками. Текстовое поле в этом режиме `readonly`
|
|
21
|
+
* и показывает значение как `min – max`.
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
range?: boolean;
|
|
25
|
+
/** Минимум */
|
|
26
|
+
min: number;
|
|
27
|
+
/** Максимум */
|
|
28
|
+
max: number;
|
|
29
|
+
/** Шаг приращения. `null` — снэп только к меткам. */
|
|
30
|
+
step: number | null;
|
|
31
|
+
/** Метки на шкале */
|
|
32
|
+
marks?: SliderMarks;
|
|
33
|
+
/**
|
|
34
|
+
* Показывать линейку с метками
|
|
35
|
+
* @default true
|
|
36
|
+
*/
|
|
37
|
+
showScaleBar?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Равномерно распределять метки по шкале при нелинейных значениях
|
|
40
|
+
* (например `1 2 4 8 16 32` — равные промежутки вместо логарифмических).
|
|
41
|
+
* @default false
|
|
42
|
+
*/
|
|
43
|
+
marksEqualSpacing?: boolean;
|
|
44
|
+
/** Форматирование значения в текстовом поле */
|
|
45
|
+
textInputFormatter?: TextInputFormatter;
|
|
46
|
+
/**
|
|
47
|
+
* Если `true` — текстовое поле принимает любые числа в диапазоне `min..max`,
|
|
48
|
+
* не снэпя к меткам.
|
|
49
|
+
* @default false
|
|
50
|
+
*/
|
|
51
|
+
unbindInputFromMarks?: boolean;
|
|
52
|
+
/** Произвольный префикс */
|
|
53
|
+
prefix?: ReactNode;
|
|
54
|
+
/** Произвольный постфикс */
|
|
55
|
+
postfix?: ReactNode;
|
|
56
|
+
/** Иконка-постфикс справа от текстового поля */
|
|
57
|
+
postfixIcon?: ReactElement;
|
|
58
|
+
/**
|
|
59
|
+
* Фон поля (acrylic)
|
|
60
|
+
* @default true
|
|
61
|
+
*/
|
|
62
|
+
background?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Показывать кнопку копирования значения (видна в readonly, при `!disabled`).
|
|
65
|
+
* @default true
|
|
66
|
+
*/
|
|
67
|
+
showCopyButton?: boolean;
|
|
68
|
+
/** Колбек после успешного копирования значения. */
|
|
69
|
+
onCopyButtonClick?(): void;
|
|
70
|
+
/** Поле выключено */
|
|
71
|
+
disabled?: boolean;
|
|
72
|
+
/** Только для чтения */
|
|
73
|
+
readonly?: boolean;
|
|
74
|
+
/** HTML id */
|
|
75
|
+
id?: string;
|
|
76
|
+
/** HTML name */
|
|
77
|
+
name?: string;
|
|
78
|
+
/** Автофокус. На mobile выключается адаптивно (см. `layoutPresets`) */
|
|
79
|
+
autoFocus?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Переопределение адаптивных дефолтов по раскладке. Участвует `autoFocus`: на mobile он выключен
|
|
82
|
+
* (открывает клавиатуру без действия). Вернуть на mobile — `layoutPresets={{ mobile: { autoFocus: true } }}`.
|
|
83
|
+
*/
|
|
84
|
+
layoutPresets?: FieldLayoutPresets;
|
|
85
|
+
/** Колбек фокуса */
|
|
86
|
+
onFocus?(event: FocusEvent<HTMLInputElement>): void;
|
|
87
|
+
/** Колбек блюра */
|
|
88
|
+
onBlur?(event: FocusEvent<HTMLInputElement>): void;
|
|
89
|
+
};
|
|
90
|
+
export type FieldSliderProps = FieldSliderDecoratorProps & FieldSliderOwnProps;
|
|
91
|
+
export declare const FieldSlider: import("react").ForwardRefExoticComponent<FieldSliderDecoratorProps & FieldSliderOwnProps & import("react").RefAttributes<HTMLInputElement>>;
|
|
92
|
+
export {};
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.FieldSlider = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const button_1 = require("@cloud-ru/ds-button");
|
|
9
|
+
const field_decorator_1 = require("@cloud-ru/ds-field-decorator");
|
|
10
|
+
const system_1 = require("@cloud-ru/ds-icons/interface/system");
|
|
11
|
+
const input_private_1 = require("@cloud-ru/ds-input-private");
|
|
12
|
+
const slider_1 = require("@cloud-ru/ds-slider");
|
|
13
|
+
const utils_1 = require("@cloud-ru/ds-utils");
|
|
14
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
15
|
+
const merge_refs_1 = __importDefault(require("merge-refs"));
|
|
16
|
+
const react_1 = require("react");
|
|
17
|
+
const constants_1 = require("../../constants");
|
|
18
|
+
const hooks_1 = require("../../hooks");
|
|
19
|
+
const shared_1 = require("../shared");
|
|
20
|
+
const styles_module_scss_1 = __importDefault(require('../shared/styles.module.css'));
|
|
21
|
+
const styles_module_scss_2 = __importDefault(require('./styles.module.css'));
|
|
22
|
+
const utils_2 = require("./utils");
|
|
23
|
+
exports.FieldSlider = (0, react_1.forwardRef)(function FieldSlider({ label = '', labelTooltip, caption, hint, error, validationState = field_decorator_1.VALIDATION_STATE.Default, showHintIcon, length, required, size = field_decorator_1.SIZE.M, className, fieldClassName, background = true, showCopyButton = true, onCopyButtonClick, value: valueProp, defaultValue, onChange, range = false, min, max, step, marks, showScaleBar = true, marksEqualSpacing, textInputFormatter, unbindInputFromMarks = false, prefix, postfix, postfixIcon, disabled, readonly: readOnly, id, name, autoFocus, layoutPresets, onFocus, onBlur, 'data-test-id': dataTestId, ...rest }, ref) {
|
|
24
|
+
const localRef = (0, react_1.useRef)(null);
|
|
25
|
+
const copyButtonRef = (0, react_1.useRef)(null);
|
|
26
|
+
const [focusVisible, setFocusVisible] = (0, react_1.useState)(false);
|
|
27
|
+
const [hover, setHover] = (0, react_1.useState)(false);
|
|
28
|
+
const [copied, setCopied] = (0, react_1.useState)(false);
|
|
29
|
+
const copiedTimerRef = (0, react_1.useRef)(undefined);
|
|
30
|
+
const resolvedAutoFocus = (0, hooks_1.useAdaptiveAutoFocus)(autoFocus, layoutPresets);
|
|
31
|
+
(0, react_1.useEffect)(() => () => {
|
|
32
|
+
if (copiedTimerRef.current) {
|
|
33
|
+
clearTimeout(copiedTimerRef.current);
|
|
34
|
+
}
|
|
35
|
+
}, []);
|
|
36
|
+
// error форсит validationState='error' поверх любого значения — паритет с сиблингами (FieldStepper и др.).
|
|
37
|
+
const effectiveValidationState = (0, react_1.useMemo)(() => (error ? field_decorator_1.VALIDATION_STATE.Error : validationState), [error, validationState]);
|
|
38
|
+
// controlled/uncontrolled: useValueControl держит значение при отсутствии `value`.
|
|
39
|
+
const [value = range ? [min, max] : min, setValue] = (0, utils_1.useValueControl)({
|
|
40
|
+
value: valueProp,
|
|
41
|
+
defaultValue,
|
|
42
|
+
});
|
|
43
|
+
const [inputValue, setInputValue] = (0, react_1.useState)(() => (0, utils_2.getTextFieldValue)(value, textInputFormatter));
|
|
44
|
+
const allowedKeys = (0, react_1.useMemo)(() => (marks ? Object.keys(marks) : []), [marks]);
|
|
45
|
+
const hasMarksEqualToValues = (0, react_1.useMemo)(() => {
|
|
46
|
+
if (!marks) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return allowedKeys.every(key => key === String((0, utils_2.getMarkLabel)(marks[key])));
|
|
50
|
+
}, [allowedKeys, marks]);
|
|
51
|
+
// Актуальное значение для рантайм-ре-снапа шкалы (см. эффект ниже).
|
|
52
|
+
const valueRef = (0, react_1.useRef)(value);
|
|
53
|
+
valueRef.current = value;
|
|
54
|
+
const commitValue = (0, react_1.useCallback)((next) => {
|
|
55
|
+
// blur/Enter — это явный commit: значение фиксируется и onChange вызывается всегда,
|
|
56
|
+
// в том числе когда введённое снапнулось обратно к текущему (контракт «blur = commit»).
|
|
57
|
+
setValue(next);
|
|
58
|
+
onChange?.(next);
|
|
59
|
+
setInputValue((0, utils_2.getTextFieldValue)(next, textInputFormatter));
|
|
60
|
+
}, [onChange, setValue, textInputFormatter]);
|
|
61
|
+
const handleSliderChange = (0, react_1.useCallback)((next) => {
|
|
62
|
+
commitValue(next);
|
|
63
|
+
}, [commitValue]);
|
|
64
|
+
const snapAndCommit = (0, react_1.useCallback)((raw) => {
|
|
65
|
+
if (range) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const parsed = parseFloat(raw);
|
|
69
|
+
if (Number.isNaN(parsed)) {
|
|
70
|
+
commitValue(value);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (parsed <= min) {
|
|
74
|
+
commitValue(min);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (parsed >= max) {
|
|
78
|
+
commitValue(max);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const allowedFromMarks = !marks || hasMarksEqualToValues || unbindInputFromMarks
|
|
82
|
+
? []
|
|
83
|
+
: allowedKeys
|
|
84
|
+
.map(key => parseFloat(String((0, utils_2.getMarkLabel)(marks[key]))))
|
|
85
|
+
.filter(mark => !Number.isNaN(mark));
|
|
86
|
+
if (allowedFromMarks.length === 0) {
|
|
87
|
+
// Снэп к допустимым значениям шага. step<=0/null → снэпа нет, принимаем число как есть.
|
|
88
|
+
if (step === null || step <= 0) {
|
|
89
|
+
commitValue(parsed);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const allowedValues = (0, utils_2.generateAllowedValues)(min, max, step);
|
|
93
|
+
if (allowedValues.includes(parsed)) {
|
|
94
|
+
commitValue(parsed);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const closest = (0, utils_2.getClosestMark)(parsed, allowedValues, m => m);
|
|
98
|
+
commitValue(closest ? closest.mark : parsed);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const closest = (0, utils_2.getClosestMark)(parsed, allowedFromMarks, m => m);
|
|
102
|
+
commitValue(closest ? closest.mark : parsed);
|
|
103
|
+
}, [allowedKeys, commitValue, hasMarksEqualToValues, marks, max, min, range, step, unbindInputFromMarks, value]);
|
|
104
|
+
const handleInputChange = (0, react_1.useCallback)((raw) => {
|
|
105
|
+
// В range-режиме поле readonly — правки игнорируем, не трогая идентичность колбека.
|
|
106
|
+
if (range) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// не пускаем нечисловой ввод в поле (паритет с легаси onTextFieldChange)
|
|
110
|
+
const parsed = parseFloat(raw);
|
|
111
|
+
if (raw && Number.isNaN(parsed)) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
setInputValue(raw);
|
|
115
|
+
}, [range]);
|
|
116
|
+
const handleInputBlur = (0, react_1.useCallback)((event) => {
|
|
117
|
+
snapAndCommit(inputValue);
|
|
118
|
+
onBlur?.(event);
|
|
119
|
+
}, [inputValue, onBlur, snapAndCommit]);
|
|
120
|
+
const handleInputFocus = (0, react_1.useCallback)((event) => {
|
|
121
|
+
setFocusVisible(event.target.matches(':focus-visible'));
|
|
122
|
+
onFocus?.(event);
|
|
123
|
+
}, [onFocus]);
|
|
124
|
+
const handleMouseEnter = (0, react_1.useCallback)(() => {
|
|
125
|
+
if (!readOnly) {
|
|
126
|
+
setHover(true);
|
|
127
|
+
}
|
|
128
|
+
}, [readOnly]);
|
|
129
|
+
const handleMouseLeave = (0, react_1.useCallback)(() => {
|
|
130
|
+
setHover(false);
|
|
131
|
+
}, []);
|
|
132
|
+
// Copy-кнопка видна только в readonly при !disabled — паритет с Figma readonly-вариантом
|
|
133
|
+
// fieldSlider (слот buttonCopy). В range-режиме инпут тоже нередактируем, но copy там не
|
|
134
|
+
// показываем: это не readonly-проп, а две ручки диапазона (в легаси copy у range не было).
|
|
135
|
+
// Копируется отображаемый текст значения (`inputValue`, с учётом textInputFormatter).
|
|
136
|
+
const showCopyUi = Boolean(showCopyButton && readOnly && !disabled);
|
|
137
|
+
const handleCopy = (0, react_1.useCallback)((event) => {
|
|
138
|
+
event.preventDefault();
|
|
139
|
+
event.stopPropagation();
|
|
140
|
+
(0, shared_1.copyTextToClipboard)(inputValue).then(copied => {
|
|
141
|
+
if (!copied) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
onCopyButtonClick?.();
|
|
145
|
+
setCopied(true);
|
|
146
|
+
if (copiedTimerRef.current) {
|
|
147
|
+
clearTimeout(copiedTimerRef.current);
|
|
148
|
+
}
|
|
149
|
+
copiedTimerRef.current = setTimeout(() => setCopied(false), 2000);
|
|
150
|
+
});
|
|
151
|
+
}, [inputValue, onCopyButtonClick]);
|
|
152
|
+
const handleInputKeyDown = (0, react_1.useCallback)((event) => {
|
|
153
|
+
if (event.key === 'Enter') {
|
|
154
|
+
snapAndCommit(inputValue);
|
|
155
|
+
}
|
|
156
|
+
// Клавиатурный путь к copy в readonly (кнопка с tabIndex −1 недостижима по Tab):
|
|
157
|
+
// ArrowRight из инпута → copy, ArrowLeft с copy — назад (handleCopyButtonKeyDown).
|
|
158
|
+
if (event.key === 'ArrowRight' && readOnly && showCopyUi && copyButtonRef.current) {
|
|
159
|
+
event.preventDefault();
|
|
160
|
+
copyButtonRef.current.focus();
|
|
161
|
+
}
|
|
162
|
+
}, [inputValue, readOnly, showCopyUi, snapAndCommit]);
|
|
163
|
+
const handleCopyButtonKeyDown = (0, react_1.useCallback)((event) => {
|
|
164
|
+
if (event.key === 'ArrowLeft') {
|
|
165
|
+
event.preventDefault();
|
|
166
|
+
localRef.current?.focus();
|
|
167
|
+
}
|
|
168
|
+
}, []);
|
|
169
|
+
(0, react_1.useEffect)(() => {
|
|
170
|
+
setInputValue((0, utils_2.getTextFieldValue)(value, textInputFormatter));
|
|
171
|
+
}, [textInputFormatter, value]);
|
|
172
|
+
// Рефы на последнюю snap-функцию и значение: пере-привязка по смене шкалы (эффект ниже)
|
|
173
|
+
// не зависит от их идентичности и не зацикливается на каждом onChange.
|
|
174
|
+
const snapAndCommitRef = (0, react_1.useRef)(snapAndCommit);
|
|
175
|
+
snapAndCommitRef.current = snapAndCommit;
|
|
176
|
+
// Рантайм-смена шкалы (marks/min/max) пере-привязывает текущее значение к новому допустимому
|
|
177
|
+
// набору (паритет с легаси re-snap effect): после, например, max 100→50 значение 75 уедет к 50.
|
|
178
|
+
// Range управляется слайдером и здесь не трогается.
|
|
179
|
+
(0, react_1.useEffect)(() => {
|
|
180
|
+
if (range) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
snapAndCommitRef.current(String(valueRef.current));
|
|
184
|
+
}, [marks, min, max, range]);
|
|
185
|
+
const shell = (
|
|
186
|
+
// data-size на корне нужен, чтобы `.sliderWrapper` (сосед `.fieldWrapper`, а не потомок)
|
|
187
|
+
// подхватил size-зависимые токены отступов трека.
|
|
188
|
+
(0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_2.default.fieldSlider, "data-size": size, children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.fieldWrapper, fieldClassName), "data-size": size, "data-validation-state": effectiveValidationState, "data-disabled": disabled || undefined, "data-readonly": readOnly || undefined, "data-withbackground": background || undefined, "data-focusvisible": focusVisible || undefined, "data-hover": !readOnly && hover ? true : undefined, "data-test-id": constants_1.TEST_IDS.fieldSliderField, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.backgroundWrapper, children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.materialLayer, ...(0, shared_1.getAcrylicProps)({
|
|
189
|
+
validationState: effectiveValidationState,
|
|
190
|
+
disabled,
|
|
191
|
+
readonly: readOnly,
|
|
192
|
+
hover,
|
|
193
|
+
focusVisible,
|
|
194
|
+
}), children: (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.acrylicBg, "aria-hidden": true }) }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.borderStateLayer, "data-state": 'borderOnBackground' }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.focusLayer })] }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.fieldContainer, children: (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.contentWrapper, children: (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.inputLine, children: [prefix && (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.prefix, children: prefix }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.inputArea, children: (0, jsx_runtime_1.jsx)(input_private_1.InputPrivate, { ref: (0, merge_refs_1.default)(ref, localRef), className: styles_module_scss_1.default.fieldInput, value: inputValue, type: input_private_1.TYPE.Text, inputMode: input_private_1.INPUT_MODE.Numeric, disabled: disabled, readonly: range || readOnly, onChange: handleInputChange, onBlur: handleInputBlur, onFocus: handleInputFocus, onKeyDown: handleInputKeyDown, id: id, name: name, autoFocus: resolvedAutoFocus, "data-test-id": constants_1.TEST_IDS.fieldSliderInput, ...(0, utils_1.extractSupportProps)(rest) }) }), showCopyUi && ((0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_2.default.copyButton, children: (0, jsx_runtime_1.jsx)(button_1.Button, { innerRef: copyButtonRef, type: 'button', view: 'function', appearance: 'neutral', size: size, icon: copied ? (0, jsx_runtime_1.jsx)(system_1.CheckSVG, {}) : (0, jsx_runtime_1.jsx)(system_1.CopySVG, {}), onClick: handleCopy, onKeyDown: handleCopyButtonKeyDown, tabIndex: -1, "data-test-id": constants_1.TEST_IDS.fieldSliderCopyButton }) })), postfix && (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.postfix, children: postfix }), postfixIcon && (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_2.default.postfixIcon, children: postfixIcon })] }) }) })] }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.sliderWrapper, children: (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.slider, children: (0, jsx_runtime_1.jsx)(slider_1.Slider, { range: range, min: min, max: max, step: step, value: value, onChange: handleSliderChange, marks: showScaleBar ? marks : undefined, marksEqualSpacing: marksEqualSpacing, disabled: readOnly || disabled, "data-test-id": constants_1.TEST_IDS.fieldSliderHandle }) }) })] }));
|
|
195
|
+
return ((0, jsx_runtime_1.jsx)(field_decorator_1.FieldDecorator, { className: className, label: label, labelTooltip: labelTooltip, caption: caption, hint: hint, error: error, validationState: validationState, showHintIcon: showHintIcon, length: length, required: required, labelFor: id, disabled: disabled, readonly: readOnly, size: size, "data-test-id": dataTestId, children: shell }));
|
|
196
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./FieldSlider"), exports);
|
|
18
|
+
__exportStar(require("./types"), exports);
|