@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,17 @@
|
|
|
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("./FieldCombo"), exports);
|
|
@@ -0,0 +1,369 @@
|
|
|
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.FieldDate = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const calendar_1 = require("@cloud-ru/ds-calendar");
|
|
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 classnames_1 = __importDefault(require("classnames"));
|
|
13
|
+
const merge_refs_1 = __importDefault(require("merge-refs"));
|
|
14
|
+
const react_1 = require("react");
|
|
15
|
+
const constants_1 = require("../../constants");
|
|
16
|
+
const hooks_1 = require("../../hooks");
|
|
17
|
+
const segments_1 = require("../../segments");
|
|
18
|
+
const shared_1 = require("../shared");
|
|
19
|
+
const styles_module_scss_1 = __importDefault(require('../shared/styles.module.css'));
|
|
20
|
+
const constants_2 = require("./constants");
|
|
21
|
+
const mask_1 = require("./mask");
|
|
22
|
+
const styles_module_scss_2 = __importDefault(require('./styles.module.css'));
|
|
23
|
+
const utils_1 = require("./utils");
|
|
24
|
+
exports.FieldDate = (0, react_1.forwardRef)(function FieldDate(props, ref) {
|
|
25
|
+
const { label = '', labelTooltip, caption, hint, error, validationState = field_decorator_1.VALIDATION_STATE.Default, showHintIcon, length, required, size = field_decorator_1.SIZE.M, className, fieldClassName, placeholder, labelFrom = constants_2.DATE_RANGE_LABELS.from, labelTo = constants_2.DATE_RANGE_LABELS.to, iconBefore, disabled, readonly: readOnly, background = true, open: openProp, onOpenChange, placement, today, showHolidays, buildCellProps, locale, presets, closeOnApply = true, closeOnPopstate, showClearButton = true, showCopyButton = true, onCopyButtonClick, showSeconds = true, id, name, autoFocus, layoutPresets, onFocus: onFocusProp, onBlur: onBlurProp, 'data-test-id': dataTestId = constants_1.TEST_IDS.fieldDate, } = props;
|
|
26
|
+
const range = (0, utils_1.isRange)(props);
|
|
27
|
+
const maskMode = props.mode === constants_2.DATE_MODE.DateTime ? constants_2.DATE_MODE.DateTime : constants_2.DATE_MODE.Date;
|
|
28
|
+
const segMode = maskMode === constants_2.DATE_MODE.DateTime ? constants_2.DATE_MODE.DateTime : constants_2.DATE_MODE.Date;
|
|
29
|
+
const { mask: segMask, slots: segSlots } = (0, react_1.useMemo)(() => (0, segments_1.buildSegments)(segMode, showSeconds), [segMode, showSeconds]);
|
|
30
|
+
const placeholderMask = placeholder ?? segMask;
|
|
31
|
+
const fromInputRef = (0, react_1.useRef)(null);
|
|
32
|
+
const toInputRef = (0, react_1.useRef)(null);
|
|
33
|
+
const clearButtonRef = (0, react_1.useRef)(null);
|
|
34
|
+
const copyButtonRef = (0, react_1.useRef)(null);
|
|
35
|
+
const navigationStartRef = (0, react_1.useRef)(null);
|
|
36
|
+
const [hover, setHover] = (0, react_1.useState)(false);
|
|
37
|
+
const [focusVisible, setFocusVisible] = (0, react_1.useState)(false);
|
|
38
|
+
const [openLocal, setOpenLocal] = (0, react_1.useState)(false);
|
|
39
|
+
const open = openProp ?? openLocal;
|
|
40
|
+
const resolvedAutoFocus = (0, hooks_1.useAdaptiveAutoFocus)(autoFocus, layoutPresets);
|
|
41
|
+
const [singleLocal, setSingleLocal] = (0, react_1.useState)(!range ? props.defaultValue : undefined);
|
|
42
|
+
const [rangeLocal, setRangeLocal] = (0, react_1.useState)(range ? (props.defaultValue ?? [undefined, undefined]) : [undefined, undefined]);
|
|
43
|
+
const singleValue = (0, react_1.useMemo)(() => (!range ? (props.value ?? singleLocal) : undefined), [range, props.value, singleLocal]);
|
|
44
|
+
const rangeValue = (0, react_1.useMemo)(() => (range ? (props.value ?? rangeLocal) : [undefined, undefined]), [range, props.value, rangeLocal]);
|
|
45
|
+
const effectiveValidationState = (0, react_1.useMemo)(() => (error ? field_decorator_1.VALIDATION_STATE.Error : validationState), [error, validationState]);
|
|
46
|
+
// Локальное состояние input'а(ов) — синхронизируется при внешних изменениях value, но не блокирует ввод.
|
|
47
|
+
const [singleInputValue, setSingleInputValue] = (0, react_1.useState)(() => !range && singleValue ? (0, mask_1.dateToMaskString)(singleValue, maskMode, showSeconds) : '');
|
|
48
|
+
const [rangeInputValue, setRangeInputValue] = (0, react_1.useState)(() => [
|
|
49
|
+
range && rangeValue[0] ? (0, mask_1.dateToMaskString)(rangeValue[0], maskMode, showSeconds) : '',
|
|
50
|
+
range && rangeValue[1] ? (0, mask_1.dateToMaskString)(rangeValue[1], maskMode, showSeconds) : '',
|
|
51
|
+
]);
|
|
52
|
+
// Зеркало `rangeInputValue` — чтобы handleRangeInput читал актуальное состояние без side-effect в updater'е.
|
|
53
|
+
const rangeInputValueRef = (0, react_1.useRef)(rangeInputValue);
|
|
54
|
+
rangeInputValueRef.current = rangeInputValue;
|
|
55
|
+
(0, react_1.useEffect)(() => {
|
|
56
|
+
if (range)
|
|
57
|
+
return;
|
|
58
|
+
const next = singleValue ? (0, mask_1.dateToMaskString)(singleValue, maskMode, showSeconds) : '';
|
|
59
|
+
if (fromInputRef.current && document.activeElement === fromInputRef.current)
|
|
60
|
+
return;
|
|
61
|
+
setSingleInputValue(next);
|
|
62
|
+
}, [singleValue, range, maskMode, showSeconds]);
|
|
63
|
+
(0, react_1.useEffect)(() => {
|
|
64
|
+
if (!range)
|
|
65
|
+
return;
|
|
66
|
+
const next = [
|
|
67
|
+
rangeValue[0] ? (0, mask_1.dateToMaskString)(rangeValue[0], maskMode, showSeconds) : '',
|
|
68
|
+
rangeValue[1] ? (0, mask_1.dateToMaskString)(rangeValue[1], maskMode, showSeconds) : '',
|
|
69
|
+
];
|
|
70
|
+
// Чтение фокуса — до updater'а (updater остаётся чистым, без side-effect/DOM-доступа).
|
|
71
|
+
const fromFocused = fromInputRef.current && document.activeElement === fromInputRef.current;
|
|
72
|
+
const toFocused = toInputRef.current && document.activeElement === toInputRef.current;
|
|
73
|
+
setRangeInputValue(prev => [fromFocused ? prev[0] : next[0], toFocused ? prev[1] : next[1]]);
|
|
74
|
+
}, [rangeValue, range, maskMode, showSeconds]);
|
|
75
|
+
const handleOpenChange = (0, react_1.useCallback)((next) => {
|
|
76
|
+
// Календарь открывается кликом по полю (CalendarDropdown дёргает onOpenChange(true)).
|
|
77
|
+
// readonly/disabled поле открывать нельзя — блокируем открытие, закрытие разрешаем.
|
|
78
|
+
if (next && (disabled || readOnly))
|
|
79
|
+
return;
|
|
80
|
+
if (openProp === undefined)
|
|
81
|
+
setOpenLocal(next);
|
|
82
|
+
onOpenChange?.(next);
|
|
83
|
+
}, [openProp, onOpenChange, disabled, readOnly]);
|
|
84
|
+
const commitSingle = (0, react_1.useCallback)((next) => {
|
|
85
|
+
if (range)
|
|
86
|
+
return;
|
|
87
|
+
if (props.value === undefined)
|
|
88
|
+
setSingleLocal(next);
|
|
89
|
+
props.onChange?.(next);
|
|
90
|
+
}, [range, props]);
|
|
91
|
+
const commitRange = (0, react_1.useCallback)((next) => {
|
|
92
|
+
if (!range)
|
|
93
|
+
return;
|
|
94
|
+
if (props.value === undefined)
|
|
95
|
+
setRangeLocal(next);
|
|
96
|
+
props.onChange?.(next);
|
|
97
|
+
}, [range, props]);
|
|
98
|
+
// Сегментный ввод одиночной даты/даты-времени (range остаётся type-through ниже).
|
|
99
|
+
const singleSeg = (0, segments_1.useSegmentedMask)({
|
|
100
|
+
inputRef: fromInputRef,
|
|
101
|
+
mask: segMask,
|
|
102
|
+
slots: segSlots,
|
|
103
|
+
readonly: readOnly,
|
|
104
|
+
disabled,
|
|
105
|
+
setValue: setSingleInputValue,
|
|
106
|
+
onMaskedChange: masked => {
|
|
107
|
+
if (masked === '') {
|
|
108
|
+
commitSingle(undefined);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const parsed = (0, mask_1.parseMask)(masked, maskMode, showSeconds);
|
|
112
|
+
if (parsed)
|
|
113
|
+
commitSingle(parsed);
|
|
114
|
+
},
|
|
115
|
+
onArrowDown: () => {
|
|
116
|
+
if (readOnly || disabled)
|
|
117
|
+
return;
|
|
118
|
+
handleOpenChange(true);
|
|
119
|
+
// Клавиатурный handoff: фокус уходит в сетку календаря (паритет с легаси checkForLeavingFocus).
|
|
120
|
+
setTimeout(() => navigationStartRef.current?.focus(), 0);
|
|
121
|
+
},
|
|
122
|
+
// ArrowUp в поле закрывает открытый календарь (фокус остаётся в input на текущем сегменте).
|
|
123
|
+
onArrowUp: () => {
|
|
124
|
+
if (readOnly || disabled)
|
|
125
|
+
return;
|
|
126
|
+
handleOpenChange(false);
|
|
127
|
+
},
|
|
128
|
+
onEscape: () => handleOpenChange(false),
|
|
129
|
+
onEdit: () => handleOpenChange(false),
|
|
130
|
+
});
|
|
131
|
+
const handleRangeInput = (0, react_1.useCallback)((idx) => (input) => {
|
|
132
|
+
const formatted = (0, mask_1.formatMask)(input, maskMode, showSeconds);
|
|
133
|
+
// Считаем следующее состояние из текущего rangeInputValue (ref), без side-effect в updater'е.
|
|
134
|
+
const prev = rangeInputValueRef.current;
|
|
135
|
+
const next = idx === 0 ? [formatted, prev[1]] : [prev[0], formatted];
|
|
136
|
+
setRangeInputValue(next);
|
|
137
|
+
const parsedFrom = next[0] ? (0, mask_1.parseMask)(next[0], maskMode, showSeconds) : undefined;
|
|
138
|
+
const parsedTo = next[1] ? (0, mask_1.parseMask)(next[1], maskMode, showSeconds) : undefined;
|
|
139
|
+
// Эмитим только когда обе даты валидны либо обе пусты — иначе ждём.
|
|
140
|
+
const bothValid = (parsedFrom !== undefined || next[0] === '') && (parsedTo !== undefined || next[1] === '');
|
|
141
|
+
if (bothValid)
|
|
142
|
+
commitRange([parsedFrom, parsedTo]);
|
|
143
|
+
}, [maskMode, showSeconds, commitRange]);
|
|
144
|
+
const handleClear = (0, react_1.useCallback)(() => {
|
|
145
|
+
if (range) {
|
|
146
|
+
setRangeInputValue(['', '']);
|
|
147
|
+
commitRange([undefined, undefined]);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
setSingleInputValue('');
|
|
151
|
+
commitSingle(undefined);
|
|
152
|
+
}
|
|
153
|
+
fromInputRef.current?.focus();
|
|
154
|
+
}, [range, commitRange, commitSingle]);
|
|
155
|
+
const handleCalendarSingleChange = (0, react_1.useCallback)((next) => {
|
|
156
|
+
if (range || disabled || readOnly)
|
|
157
|
+
return;
|
|
158
|
+
commitSingle(next);
|
|
159
|
+
// Sync-эффект пропускает обновление сфокусированного input'а — обновляем строку сами.
|
|
160
|
+
const nextStr = next ? (0, mask_1.dateToMaskString)(next, maskMode, showSeconds) : '';
|
|
161
|
+
setSingleInputValue(nextStr);
|
|
162
|
+
// Императивно кладём строку в DOM ДО focus(): клик по дате блюрит input → handleBlur движка
|
|
163
|
+
// сбрасывает `input.value` (был === mask) в ''. Возврат фокуса синхронно вызывает
|
|
164
|
+
// `ensureMask`, который на пустом DOM пишет mask обратно и перетирает только что выбранную
|
|
165
|
+
// дату (setSingleInputValue ещё не применён React'ом). Синхронизируем DOM сами — ensureMask
|
|
166
|
+
// видит непустое значение и no-op'ает (баг: маска «залипала» в value-цвете после выбора).
|
|
167
|
+
if (fromInputRef.current) {
|
|
168
|
+
fromInputRef.current.value = nextStr;
|
|
169
|
+
}
|
|
170
|
+
// Выбор даты возвращает фокус в input и закрывает календарь (легаси handleSelectDate).
|
|
171
|
+
// В date-time onChangeValue эмитится только по Apply (клик по дате копит internal state
|
|
172
|
+
// календаря), поэтому выбор времени закрытием не обрывается — паритет с легаси.
|
|
173
|
+
fromInputRef.current?.focus();
|
|
174
|
+
handleOpenChange(false);
|
|
175
|
+
}, [range, disabled, readOnly, commitSingle, maskMode, showSeconds, handleOpenChange]);
|
|
176
|
+
const handleCalendarRangeChange = (0, react_1.useCallback)((next) => {
|
|
177
|
+
if (!range || disabled || readOnly)
|
|
178
|
+
return;
|
|
179
|
+
commitRange(next);
|
|
180
|
+
// Закрываем только когда выбраны оба конца периода (календарь эмитит полный Range).
|
|
181
|
+
if (next[0] && next[1]) {
|
|
182
|
+
setRangeInputValue([
|
|
183
|
+
(0, mask_1.dateToMaskString)(next[0], maskMode, showSeconds),
|
|
184
|
+
(0, mask_1.dateToMaskString)(next[1], maskMode, showSeconds),
|
|
185
|
+
]);
|
|
186
|
+
fromInputRef.current?.focus();
|
|
187
|
+
handleOpenChange(false);
|
|
188
|
+
}
|
|
189
|
+
}, [range, disabled, readOnly, commitRange, maskMode, showSeconds, handleOpenChange]);
|
|
190
|
+
// Общие input-обработчики range-инпутов (`inputCommon` ниже). Открытие календаря — за
|
|
191
|
+
// click-триггером Dropdown и ArrowDown (легаси-паритет); open-on-focus конфликтовал с
|
|
192
|
+
// click-toggle (первый клик открывал и тут же закрывал календарь).
|
|
193
|
+
const handleInputFocus = (0, react_1.useCallback)((event) => {
|
|
194
|
+
setFocusVisible(event.target.matches(':focus-visible'));
|
|
195
|
+
onFocusProp?.(event);
|
|
196
|
+
}, [onFocusProp]);
|
|
197
|
+
const handleInputBlur = (0, react_1.useCallback)((event) => {
|
|
198
|
+
setFocusVisible(false);
|
|
199
|
+
onBlurProp?.(event);
|
|
200
|
+
}, [onBlurProp]);
|
|
201
|
+
const handleInputKeyDown = (0, react_1.useCallback)((event) => {
|
|
202
|
+
if (disabled || readOnly)
|
|
203
|
+
return;
|
|
204
|
+
if (event.key === 'Escape' && open) {
|
|
205
|
+
event.preventDefault();
|
|
206
|
+
handleOpenChange(false);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
// ArrowDown открывает календарь и передаёт фокус в сетку — тот же клавиатурный handoff,
|
|
210
|
+
// что у singleSeg.onArrowDown (легаси checkForLeavingFocus).
|
|
211
|
+
if (event.key === 'ArrowDown') {
|
|
212
|
+
event.preventDefault();
|
|
213
|
+
handleOpenChange(true);
|
|
214
|
+
setTimeout(() => navigationStartRef.current?.focus(), 0);
|
|
215
|
+
}
|
|
216
|
+
// ArrowUp закрывает открытый календарь (фокус остаётся в range-input).
|
|
217
|
+
if (event.key === 'ArrowUp' && open) {
|
|
218
|
+
event.preventDefault();
|
|
219
|
+
handleOpenChange(false);
|
|
220
|
+
}
|
|
221
|
+
}, [disabled, readOnly, open, handleOpenChange]);
|
|
222
|
+
// Single-input делегирует фокус/блюр сегментному движку, поэтому отдельные обработчики.
|
|
223
|
+
const handleSingleFocus = (0, react_1.useCallback)((event) => {
|
|
224
|
+
setFocusVisible(event.target.matches(':focus-visible'));
|
|
225
|
+
singleSeg.handleFocus();
|
|
226
|
+
onFocusProp?.(event);
|
|
227
|
+
}, [singleSeg, onFocusProp]);
|
|
228
|
+
const handleSingleBlur = (0, react_1.useCallback)((event) => {
|
|
229
|
+
setFocusVisible(false);
|
|
230
|
+
singleSeg.handleBlur();
|
|
231
|
+
onBlurProp?.(event);
|
|
232
|
+
}, [singleSeg, onBlurProp]);
|
|
233
|
+
const handleCalendarFocusLeave = (0, react_1.useCallback)(() => {
|
|
234
|
+
fromInputRef.current?.focus();
|
|
235
|
+
handleOpenChange(false);
|
|
236
|
+
}, [handleOpenChange]);
|
|
237
|
+
const handleMouseEnter = (0, react_1.useCallback)(() => {
|
|
238
|
+
if (!readOnly && !disabled) {
|
|
239
|
+
setHover(true);
|
|
240
|
+
}
|
|
241
|
+
}, [readOnly, disabled]);
|
|
242
|
+
const handleMouseLeave = (0, react_1.useCallback)(() => {
|
|
243
|
+
setHover(false);
|
|
244
|
+
}, []);
|
|
245
|
+
const valueToCopy = range ? [rangeInputValue[0], rangeInputValue[1]].filter(Boolean).join(' – ') : singleInputValue;
|
|
246
|
+
// Галочку «скопировано» рисует useCopyButton по `true`-результату (паритет с FieldCombo/FieldTime).
|
|
247
|
+
const handleCopy = (0, react_1.useCallback)(async () => {
|
|
248
|
+
const copied = Boolean(valueToCopy) && (await (0, shared_1.copyTextToClipboard)(valueToCopy));
|
|
249
|
+
if (copied) {
|
|
250
|
+
onCopyButtonClick?.();
|
|
251
|
+
}
|
|
252
|
+
return copied;
|
|
253
|
+
}, [onCopyButtonClick, valueToCopy]);
|
|
254
|
+
const hasValue = range ? Boolean(rangeValue[0] || rangeValue[1]) : singleValue !== undefined;
|
|
255
|
+
const showClear = Boolean(showClearButton && hasValue && !disabled && !readOnly);
|
|
256
|
+
const showCopy = Boolean(showCopyButton && hasValue && readOnly && !disabled);
|
|
257
|
+
const clearButtonSettings = (0, input_private_1.useClearButton)({
|
|
258
|
+
clearButtonRef,
|
|
259
|
+
showClearButton: showClear,
|
|
260
|
+
size: (0, shared_1.toInputSize)(size),
|
|
261
|
+
onClear: handleClear,
|
|
262
|
+
disabled: Boolean(disabled || readOnly),
|
|
263
|
+
dataTestId: constants_1.TEST_IDS.fieldDateClear,
|
|
264
|
+
});
|
|
265
|
+
const copyButtonSettings = (0, shared_1.useCopyButton)({
|
|
266
|
+
copyButtonRef,
|
|
267
|
+
showCopyButton: showCopy,
|
|
268
|
+
size: (0, shared_1.toInputSize)(size),
|
|
269
|
+
onCopy: handleCopy,
|
|
270
|
+
disabled: Boolean(disabled),
|
|
271
|
+
dataTestId: constants_1.TEST_IDS.fieldDateCopy,
|
|
272
|
+
});
|
|
273
|
+
// ArrowDown с postfix-кнопки открывает календарь и передаёт фокус в сетку
|
|
274
|
+
// (легаси checkForLeavingFocus на onButtonKeyDown).
|
|
275
|
+
const handlePostfixButtonKeyDown = (0, react_1.useCallback)((event) => {
|
|
276
|
+
if (event.key === 'ArrowDown' && !disabled && !readOnly) {
|
|
277
|
+
handleOpenChange(true);
|
|
278
|
+
setTimeout(() => navigationStartRef.current?.focus(), 0);
|
|
279
|
+
}
|
|
280
|
+
}, [disabled, readOnly, handleOpenChange]);
|
|
281
|
+
// Возврат фокуса с кнопок (ArrowLeft): handleFocus движка выбирает первый сегмент, а возврат
|
|
282
|
+
// идёт «справа» — перевыбираем последний (легаси setInputFocusFromButtons: Year/Seconds).
|
|
283
|
+
const setInputFocusFromButtons = (0, react_1.useCallback)(() => {
|
|
284
|
+
if (range) {
|
|
285
|
+
toInputRef.current?.focus();
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
fromInputRef.current?.focus();
|
|
289
|
+
singleSeg.selectSlot(singleSeg.lastSlot);
|
|
290
|
+
}, [range, singleSeg]);
|
|
291
|
+
const { postfixButtons, inputTabIndex, onInputKeyDown } = (0, input_private_1.useButtonNavigation)({
|
|
292
|
+
// Roving-композит живёт на «последнем» инпуте перед кнопками: single или range «to».
|
|
293
|
+
inputRef: range ? toInputRef : fromInputRef,
|
|
294
|
+
setInputFocus: setInputFocusFromButtons,
|
|
295
|
+
postfixButtons: (0, react_1.useMemo)(() => [clearButtonSettings, copyButtonSettings], [clearButtonSettings, copyButtonSettings]),
|
|
296
|
+
onButtonKeyDown: handlePostfixButtonKeyDown,
|
|
297
|
+
readonly: Boolean(readOnly),
|
|
298
|
+
submitKeys: ['Enter', 'Space', 'Tab'],
|
|
299
|
+
});
|
|
300
|
+
// Нав-цепочка бежит безусловно ПОСЛЕ движка (легаси useHandlers): движок ставит каретку в конец
|
|
301
|
+
// на ArrowRight с последнего сегмента, nav читает её в том же keydown и забирает фокус на кнопку.
|
|
302
|
+
const handleSingleKeyDown = (0, react_1.useCallback)((event) => {
|
|
303
|
+
singleSeg.handleKeyDown(event);
|
|
304
|
+
onInputKeyDown(event);
|
|
305
|
+
}, [singleSeg, onInputKeyDown]);
|
|
306
|
+
const handleToInputKeyDown = (0, react_1.useCallback)((event) => {
|
|
307
|
+
handleInputKeyDown(event);
|
|
308
|
+
onInputKeyDown(event);
|
|
309
|
+
}, [handleInputKeyDown, onInputKeyDown]);
|
|
310
|
+
const inputCommon = {
|
|
311
|
+
disabled,
|
|
312
|
+
readonly: readOnly,
|
|
313
|
+
inputMode: 'numeric',
|
|
314
|
+
onFocus: handleInputFocus,
|
|
315
|
+
onBlur: handleInputBlur,
|
|
316
|
+
onKeyDown: handleInputKeyDown,
|
|
317
|
+
};
|
|
318
|
+
const trigger = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.fieldWrapper, styles_module_scss_2.default.trigger, fieldClassName), "data-size": size, "data-validation-state": effectiveValidationState, "data-disabled": disabled || undefined, "data-readonly": readOnly || undefined, "data-withbackground": background || undefined, "data-focusvisible": focusVisible || open || undefined, "data-hover": !readOnly && !disabled && hover ? true : undefined, "data-test-id": dataTestId, 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)({
|
|
319
|
+
validationState: effectiveValidationState,
|
|
320
|
+
disabled,
|
|
321
|
+
readonly: readOnly,
|
|
322
|
+
hover,
|
|
323
|
+
focusVisible: focusVisible || open,
|
|
324
|
+
}), 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.jsxs)("div", { className: styles_module_scss_1.default.contentWrapper, children: [iconBefore && (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.iconSlot, children: iconBefore }), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.inputLine, children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.inputArea, children: range ? (
|
|
325
|
+
// --field-date-mask-ch — длина маски для ширины from-инпута (.rangeInputFrom, ширина в ch):
|
|
326
|
+
// «дата – дата» слитно слева, остаток поля забирает to-инпут.
|
|
327
|
+
(0, jsx_runtime_1.jsxs)("span", { className: styles_module_scss_2.default.rangeInputs, style: { '--field-date-mask-ch': placeholderMask.length }, children: [(0, jsx_runtime_1.jsx)(input_private_1.InputPrivate, { ...inputCommon, ref: (0, merge_refs_1.default)(ref, fromInputRef), className: (0, classnames_1.default)(styles_module_scss_1.default.fieldInput, styles_module_scss_2.default.rangeInputFrom), value: rangeInputValue[0], placeholder: placeholderMask, onChange: handleRangeInput(0), id: id, name: name, autoFocus: resolvedAutoFocus, "aria-label": labelFrom, "data-test-id": constants_1.TEST_IDS.fieldDateInputFrom }), (0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_2.default.rangeSeparator, "aria-hidden": true, children: "\u2013" }), (0, jsx_runtime_1.jsx)(input_private_1.InputPrivate, { ...inputCommon, ref: toInputRef, className: styles_module_scss_1.default.fieldInput, value: rangeInputValue[1], placeholder: placeholderMask, onChange: handleRangeInput(1),
|
|
328
|
+
// «to» — последний инпут перед кнопками: на нём живёт roving-композит
|
|
329
|
+
// (ArrowRight в конце → clear/copy), keydown-цепочка с nav-handler'ом.
|
|
330
|
+
onKeyDown: handleToInputKeyDown, tabIndex: inputTabIndex, "aria-label": labelTo, "data-test-id": constants_1.TEST_IDS.fieldDateInputTo })] })) : ((0, jsx_runtime_1.jsx)(input_private_1.InputPrivate, { ref: (0, merge_refs_1.default)(ref, fromInputRef), className: styles_module_scss_1.default.fieldInput, value: singleInputValue, placeholder: placeholderMask,
|
|
331
|
+
// Single/date-time ведёт сегментный движок (keydown, useSegmentedMask), нативный
|
|
332
|
+
// onChange игнорируется. Range — обычный ввод-по-маске (formatMask в handleRangeInput).
|
|
333
|
+
onChange: () => { }, onKeyDown: handleSingleKeyDown, onClick: singleSeg.handleClick, onPaste: singleSeg.handlePaste, onFocus: handleSingleFocus, onBlur: handleSingleBlur, disabled: disabled, readonly: readOnly, inputMode: 'numeric', tabIndex: inputTabIndex, id: id, name: name, autoFocus: resolvedAutoFocus, "aria-haspopup": 'dialog', "aria-expanded": open, "data-test-id": constants_1.TEST_IDS.fieldDateInput })) }), postfixButtons && (
|
|
334
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
335
|
+
(0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.postfixButtonsSlot, onMouseDown: shared_1.preventSlotMouseDown, onClick: shared_1.stopSlotClickPropagation, children: postfixButtons }))] }), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.iconSlot, "data-test-id": constants_1.TEST_IDS.fieldDateCalendar, "aria-hidden": true, children: (0, jsx_runtime_1.jsx)(system_1.CalendarSVG, {}) })] }) })] }));
|
|
336
|
+
let calendarProps;
|
|
337
|
+
if (range) {
|
|
338
|
+
// @cloud-ru/ds-calendar ожидает `Range = [Date, Date]` (оба края обязательны) и в date-range падает на
|
|
339
|
+
// `[undefined, …]` (getInRangePosition → .getFullYear() на undefined). FieldDate допускает частично
|
|
340
|
+
// заполненный период, поэтому передаём в сетку value только когда обе даты реальны — иначе undefined
|
|
341
|
+
// (нет выделения), а ввод периода продолжает работать через инпуты.
|
|
342
|
+
const bothEndsFilled = rangeValue[0] !== undefined && rangeValue[1] !== undefined;
|
|
343
|
+
calendarProps = {
|
|
344
|
+
mode: constants_2.DATE_MODE.DateRange,
|
|
345
|
+
value: bothEndsFilled ? rangeValue : undefined,
|
|
346
|
+
onChangeValue: handleCalendarRangeChange,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
else if (maskMode === constants_2.DATE_MODE.DateTime) {
|
|
350
|
+
calendarProps = {
|
|
351
|
+
mode: constants_2.DATE_MODE.DateTime,
|
|
352
|
+
value: singleValue,
|
|
353
|
+
onChangeValue: handleCalendarSingleChange,
|
|
354
|
+
showSeconds,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
calendarProps = {
|
|
359
|
+
mode: constants_2.DATE_MODE.Date,
|
|
360
|
+
value: singleValue,
|
|
361
|
+
onChangeValue: handleCalendarSingleChange,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
return ((0, jsx_runtime_1.jsx)(field_decorator_1.FieldDecorator, { className: className, label: label, labelTooltip: labelTooltip, caption: caption, hint: hint, error: error, size: size, validationState: validationState, showHintIcon: showHintIcon, length: length, required: required, labelFor: id, disabled: disabled, readonly: readOnly, children: (0, jsx_runtime_1.jsx)(calendar_1.CalendarDropdown
|
|
365
|
+
// CalendarDropdown ожидает `Range = [Date, Date]` в режиме date-range, а FieldDate хранит
|
|
366
|
+
// `[Date | undefined, Date | undefined]` (период может быть заполнен частично). Локализованный
|
|
367
|
+
// cast в `mode`-union календаря — единственная точка, где сходятся эти представления периода.
|
|
368
|
+
, { ...calendarProps, "data-test-id": constants_1.TEST_IDS.fieldDateCalendarDropdown, size: size, open: open, onOpenChange: handleOpenChange, placement: placement ?? 'bottom-start', today: today, showHolidays: showHolidays, buildCellProps: buildCellProps, locale: locale, presets: presets, closeOnApply: closeOnApply, closeOnPopstate: closeOnPopstate, navigationStartRef: navigationStartRef, onFocusLeave: handleCalendarFocusLeave, children: trigger }) }));
|
|
369
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const DATE_MODE: {
|
|
2
|
+
readonly Date: "date";
|
|
3
|
+
readonly DateTime: "date-time";
|
|
4
|
+
readonly DateRange: "date-range";
|
|
5
|
+
};
|
|
6
|
+
/** Дефолтные aria-label'ы полей периода (RU — паритет с языком компонента по умолчанию). */
|
|
7
|
+
export declare const DATE_RANGE_LABELS: {
|
|
8
|
+
readonly from: "Начало периода";
|
|
9
|
+
readonly to: "Конец периода";
|
|
10
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DATE_RANGE_LABELS = exports.DATE_MODE = void 0;
|
|
4
|
+
exports.DATE_MODE = {
|
|
5
|
+
Date: 'date',
|
|
6
|
+
DateTime: 'date-time',
|
|
7
|
+
DateRange: 'date-range',
|
|
8
|
+
};
|
|
9
|
+
/** Дефолтные aria-label'ы полей периода (RU — паритет с языком компонента по умолчанию). */
|
|
10
|
+
exports.DATE_RANGE_LABELS = {
|
|
11
|
+
from: 'Начало периода',
|
|
12
|
+
to: 'Конец периода',
|
|
13
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
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("./FieldDate"), exports);
|
|
18
|
+
__exportStar(require("./constants"), exports);
|
|
19
|
+
__exportStar(require("./types"), exports);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DATE_MODE } from './constants';
|
|
2
|
+
/** Маска поддерживает только `date` / `date-time` (range собирается из двух одиночных масок). */
|
|
3
|
+
export type MaskMode = typeof DATE_MODE.Date | typeof DATE_MODE.DateTime;
|
|
4
|
+
export declare function getMaskString(mode: MaskMode, showSeconds?: boolean): string;
|
|
5
|
+
/**
|
|
6
|
+
* Принимает любую строку, оставляет только цифры и форматирует под `DD.MM.YYYY[, HH:mm[:ss]]`.
|
|
7
|
+
*
|
|
8
|
+
* Две UX-механики, призванные не дать пользователю набрать невалидный сегмент:
|
|
9
|
+
* 1. **Авто-prefix `0`**: если первая цифра 2-цифрового сегмента превышает максимально допустимую
|
|
10
|
+
* «десятку» (`day` → > 3, `month` → > 1, `hour` → > 2, `minute`/`second` → > 5), цифра трактуется
|
|
11
|
+
* как «единицы» и в начало сегмента добавляется ноль. Пример: `5` для day → `05.`,
|
|
12
|
+
* фокус автоматически уезжает на следующий сегмент.
|
|
13
|
+
* 2. **Clamp полной двойки**: если набрано две цифры и значение превышает `max` сегмента —
|
|
14
|
+
* значение прижимается к верхней границе. Пример: `55` для day → `31`, `99` для month → `12`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatMask(input: string, mode: MaskMode, showSeconds?: boolean): string;
|
|
17
|
+
/** Парсит `DD.MM.YYYY` или `DD.MM.YYYY, HH:mm[:ss]` в `Date`. Возвращает `undefined` при невалидной/неполной строке. */
|
|
18
|
+
export declare function parseMask(input: string, mode: MaskMode, showSeconds?: boolean): Date | undefined;
|
|
19
|
+
/** Форматирует `Date` в строку под маску — для синхронизации с input при внешнем onChange. */
|
|
20
|
+
export declare function dateToMaskString(value: Date, mode: MaskMode, showSeconds?: boolean): string;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getMaskString = getMaskString;
|
|
4
|
+
exports.formatMask = formatMask;
|
|
5
|
+
exports.parseMask = parseMask;
|
|
6
|
+
exports.dateToMaskString = dateToMaskString;
|
|
7
|
+
const constants_1 = require("./constants");
|
|
8
|
+
const DATE_LEN = 8;
|
|
9
|
+
const DATE_TIME_LEN = 12;
|
|
10
|
+
const DATE_TIME_SECONDS_LEN = 14;
|
|
11
|
+
// Плейсхолдер по умолчанию — RU (ДД.ММ.ГГГГ), как в легаси @snack-uikit/fields и Figma.
|
|
12
|
+
// Структура парсинга остаётся числовой (DD/MM/YYYY[/HH/mm/ss]) — плейсхолдер только визуальный.
|
|
13
|
+
const RU_DATE = 'ДД.ММ.ГГГГ';
|
|
14
|
+
// Время отделяется запятой (паритет с легаси `ДД.ММ.ГГГГ, чч:мм:сс`).
|
|
15
|
+
const TIME_SEPARATOR = ', ';
|
|
16
|
+
function totalLen(mode, showSeconds) {
|
|
17
|
+
if (mode === constants_1.DATE_MODE.Date) {
|
|
18
|
+
return DATE_LEN;
|
|
19
|
+
}
|
|
20
|
+
return showSeconds ? DATE_TIME_SECONDS_LEN : DATE_TIME_LEN;
|
|
21
|
+
}
|
|
22
|
+
function getMaskString(mode, showSeconds = true) {
|
|
23
|
+
if (mode === constants_1.DATE_MODE.Date) {
|
|
24
|
+
return RU_DATE;
|
|
25
|
+
}
|
|
26
|
+
return showSeconds ? `${RU_DATE}${TIME_SEPARATOR}чч:мм:сс` : `${RU_DATE}${TIME_SEPARATOR}чч:мм`;
|
|
27
|
+
}
|
|
28
|
+
function buildSegments(mode, showSeconds) {
|
|
29
|
+
const base = [
|
|
30
|
+
{ len: 2, max: 31, separator: '' }, // day
|
|
31
|
+
{ len: 2, max: 12, separator: '.' }, // month
|
|
32
|
+
{ len: 4, max: 9999, separator: '.' }, // year
|
|
33
|
+
];
|
|
34
|
+
if (mode === constants_1.DATE_MODE.DateTime) {
|
|
35
|
+
base.push({ len: 2, max: 23, separator: TIME_SEPARATOR }); // hour
|
|
36
|
+
base.push({ len: 2, max: 59, separator: ':' }); // minute
|
|
37
|
+
if (showSeconds) {
|
|
38
|
+
base.push({ len: 2, max: 59, separator: ':' }); // second
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return base;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Принимает любую строку, оставляет только цифры и форматирует под `DD.MM.YYYY[, HH:mm[:ss]]`.
|
|
45
|
+
*
|
|
46
|
+
* Две UX-механики, призванные не дать пользователю набрать невалидный сегмент:
|
|
47
|
+
* 1. **Авто-prefix `0`**: если первая цифра 2-цифрового сегмента превышает максимально допустимую
|
|
48
|
+
* «десятку» (`day` → > 3, `month` → > 1, `hour` → > 2, `minute`/`second` → > 5), цифра трактуется
|
|
49
|
+
* как «единицы» и в начало сегмента добавляется ноль. Пример: `5` для day → `05.`,
|
|
50
|
+
* фокус автоматически уезжает на следующий сегмент.
|
|
51
|
+
* 2. **Clamp полной двойки**: если набрано две цифры и значение превышает `max` сегмента —
|
|
52
|
+
* значение прижимается к верхней границе. Пример: `55` для day → `31`, `99` для month → `12`.
|
|
53
|
+
*/
|
|
54
|
+
function formatMask(input, mode, showSeconds = true) {
|
|
55
|
+
const maxLen = totalLen(mode, showSeconds);
|
|
56
|
+
const segments = buildSegments(mode, showSeconds);
|
|
57
|
+
let stream = input.replace(/\D/g, '').slice(0, maxLen);
|
|
58
|
+
let out = '';
|
|
59
|
+
for (const seg of segments) {
|
|
60
|
+
if (stream.length === 0)
|
|
61
|
+
break;
|
|
62
|
+
out += seg.separator;
|
|
63
|
+
// Auto-zero-prefix: если первая цифра > floor(max/10), сегмент не может начаться этой цифрой —
|
|
64
|
+
// считаем её цифрой «единиц» и дописываем `0` перед ней.
|
|
65
|
+
if (seg.len === 2) {
|
|
66
|
+
const first = Number(stream[0]);
|
|
67
|
+
const firstMax = Math.floor(seg.max / 10);
|
|
68
|
+
if (first > firstMax) {
|
|
69
|
+
out += `0${stream[0]}`;
|
|
70
|
+
stream = stream.slice(1);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const raw = stream.slice(0, seg.len);
|
|
75
|
+
stream = stream.slice(seg.len);
|
|
76
|
+
if (raw.length === seg.len) {
|
|
77
|
+
const n = Number(raw);
|
|
78
|
+
out += n > seg.max ? String(seg.max).padStart(seg.len, '0') : raw;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
out += raw;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
/** Парсит `DD.MM.YYYY` или `DD.MM.YYYY, HH:mm[:ss]` в `Date`. Возвращает `undefined` при невалидной/неполной строке. */
|
|
87
|
+
function parseMask(input, mode, showSeconds = true) {
|
|
88
|
+
const digits = input.replace(/\D/g, '');
|
|
89
|
+
const expected = totalLen(mode, showSeconds);
|
|
90
|
+
if (digits.length !== expected)
|
|
91
|
+
return undefined;
|
|
92
|
+
const day = Number(digits.slice(0, 2));
|
|
93
|
+
const month = Number(digits.slice(2, 4)) - 1;
|
|
94
|
+
const year = Number(digits.slice(4, 8));
|
|
95
|
+
const hour = mode === constants_1.DATE_MODE.DateTime ? Number(digits.slice(8, 10)) : 0;
|
|
96
|
+
const minute = mode === constants_1.DATE_MODE.DateTime ? Number(digits.slice(10, 12)) : 0;
|
|
97
|
+
const second = mode === constants_1.DATE_MODE.DateTime && showSeconds ? Number(digits.slice(12, 14)) : 0;
|
|
98
|
+
if (year < 1 || month < 0 || month > 11 || day < 1 || day > 31)
|
|
99
|
+
return undefined;
|
|
100
|
+
if (hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59)
|
|
101
|
+
return undefined;
|
|
102
|
+
const d = new Date(year, month, day, hour, minute, second);
|
|
103
|
+
// Отбраковать «перетекание» вроде 30 февраля → 2 марта.
|
|
104
|
+
if (d.getDate() !== day || d.getMonth() !== month || d.getFullYear() !== year)
|
|
105
|
+
return undefined;
|
|
106
|
+
return d;
|
|
107
|
+
}
|
|
108
|
+
/** Форматирует `Date` в строку под маску — для синхронизации с input при внешнем onChange. */
|
|
109
|
+
function dateToMaskString(value, mode, showSeconds = true) {
|
|
110
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
111
|
+
const head = `${pad(value.getDate())}.${pad(value.getMonth() + 1)}.${value.getFullYear()}`;
|
|
112
|
+
if (mode !== constants_1.DATE_MODE.DateTime) {
|
|
113
|
+
return head;
|
|
114
|
+
}
|
|
115
|
+
const time = `${pad(value.getHours())}:${pad(value.getMinutes())}${showSeconds ? `:${pad(value.getSeconds())}` : ''}`;
|
|
116
|
+
return `${head}${TIME_SEPARATOR}${time}`;
|
|
117
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
.trigger{
|
|
2
|
+
cursor:pointer;
|
|
3
|
+
}
|
|
4
|
+
.trigger[data-disabled=true]{
|
|
5
|
+
cursor:not-allowed;
|
|
6
|
+
}
|
|
7
|
+
.trigger[data-readonly=true]{
|
|
8
|
+
cursor:default;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.rangeInputs{
|
|
12
|
+
display:inline-flex;
|
|
13
|
+
flex:1 1 0;
|
|
14
|
+
align-items:center;
|
|
15
|
+
min-width:0;
|
|
16
|
+
}
|
|
17
|
+
[data-size=s] .rangeInputs{
|
|
18
|
+
gap:var(--sn-field-anatomy-size-s-fieldContainer-contentWrapper-inputLine-gap, var(--sn-density-spacing-control-wrapper-horizontal-s, var(--sn-primitive-dimension-8, 8px)));
|
|
19
|
+
}
|
|
20
|
+
[data-size=m] .rangeInputs{
|
|
21
|
+
gap:var(--sn-field-anatomy-size-m-fieldContainer-contentWrapper-inputLine-gap, var(--sn-density-spacing-control-wrapper-horizontal-m, var(--sn-primitive-dimension-8, 8px)));
|
|
22
|
+
}
|
|
23
|
+
[data-size=l] .rangeInputs{
|
|
24
|
+
gap:var(--sn-field-anatomy-size-l-fieldContainer-contentWrapper-inputLine-gap, var(--sn-density-spacing-control-wrapper-horizontal-l, var(--sn-primitive-dimension-12, 12px)));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.rangeInputFrom{
|
|
28
|
+
flex:0 0 auto;
|
|
29
|
+
width:calc(var(--field-date-mask-ch, 10) * 1ch);
|
|
30
|
+
text-align:start;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@supports (field-sizing: content){
|
|
34
|
+
.rangeInputFrom{
|
|
35
|
+
field-sizing:content;
|
|
36
|
+
width:auto;
|
|
37
|
+
max-width:calc(var(--field-date-mask-ch, 10) * 1ch);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
.rangeSeparator{
|
|
41
|
+
flex-shrink:0;
|
|
42
|
+
color:var(--sn-theme-color-available-version-textTertiary, var(--sn-brand-color-text-version-tertiary, rgba(65, 66, 78, 0.5490196078)));
|
|
43
|
+
}
|