@alfalab/core-components-select 17.10.1 → 17.12.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/components/arrow/Component.js +1 -1
- package/components/arrow/index.css +3 -3
- package/components/base-checkmark/Component.js +1 -1
- package/components/base-checkmark/index.css +6 -6
- package/components/base-option/Component.js +1 -1
- package/components/base-option/index.css +18 -17
- package/components/base-select/Component.js +2 -2
- package/components/base-select/components/list-desktop/list-popover-desktop.js +1 -1
- package/components/base-select/components/list-mobile/list-bottom-sheet-mobile.js +1 -1
- package/components/base-select/components/list-mobile/list-modal-mobile.js +1 -1
- package/components/base-select/index.css +24 -22
- package/components/base-select/mobile.css +16 -15
- package/components/checkmark/Component.js +1 -1
- package/components/checkmark/index.css +12 -11
- package/components/checkmark-mobile/Component.js +1 -1
- package/components/checkmark-mobile/index.css +6 -6
- package/components/clear-button/Component.js +1 -1
- package/components/clear-button/index.css +6 -6
- package/components/field/Component.js +1 -1
- package/components/field/index.css +12 -12
- package/components/footer/Component.js +1 -1
- package/components/footer/index.css +5 -5
- package/components/optgroup/Component.js +1 -1
- package/components/optgroup/index.css +6 -6
- package/components/option/Component.js +1 -1
- package/components/option/index.css +21 -21
- package/components/options-list/Component.js +3 -3
- package/components/options-list/index.css +14 -11
- package/components/search/Component.js +1 -1
- package/components/search/index.css +2 -2
- package/components/virtual-options-list/Component.js +1 -1
- package/components/virtual-options-list/index.css +20 -19
- package/cssm/components/base-option/index.module.css +3 -2
- package/cssm/components/base-select/index.module.css +13 -11
- package/cssm/components/base-select/mobile.module.css +4 -3
- package/cssm/components/checkmark/index.module.css +2 -1
- package/cssm/components/option/index.module.css +2 -2
- package/cssm/components/options-list/Component.js +2 -2
- package/cssm/components/options-list/index.module.css +4 -1
- package/cssm/components/virtual-options-list/index.module.css +5 -4
- package/cssm/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css +3 -1
- package/cssm/presets/useSelectWithApply/options-list-with-apply/footer/vars.css +0 -0
- package/cssm/utils.d.ts +1 -1
- package/cssm/utils.js +11 -0
- package/esm/components/arrow/Component.js +1 -1
- package/esm/components/arrow/index.css +3 -3
- package/esm/components/base-checkmark/Component.js +1 -1
- package/esm/components/base-checkmark/index.css +6 -6
- package/esm/components/base-option/Component.js +1 -1
- package/esm/components/base-option/index.css +18 -17
- package/esm/components/base-select/Component.js +2 -2
- package/esm/components/base-select/components/list-desktop/list-popover-desktop.js +1 -1
- package/esm/components/base-select/components/list-mobile/list-bottom-sheet-mobile.js +1 -1
- package/esm/components/base-select/components/list-mobile/list-modal-mobile.js +1 -1
- package/esm/components/base-select/index.css +24 -22
- package/esm/components/base-select/mobile.css +16 -15
- package/esm/components/checkmark/Component.js +1 -1
- package/esm/components/checkmark/index.css +12 -11
- package/esm/components/checkmark-mobile/Component.js +1 -1
- package/esm/components/checkmark-mobile/index.css +6 -6
- package/esm/components/clear-button/Component.js +1 -1
- package/esm/components/clear-button/index.css +6 -6
- package/esm/components/field/Component.js +1 -1
- package/esm/components/field/index.css +12 -12
- package/esm/components/footer/Component.js +1 -1
- package/esm/components/footer/index.css +5 -5
- package/esm/components/optgroup/Component.js +1 -1
- package/esm/components/optgroup/index.css +6 -6
- package/esm/components/option/Component.js +1 -1
- package/esm/components/option/index.css +21 -21
- package/esm/components/options-list/Component.js +3 -3
- package/esm/components/options-list/index.css +14 -11
- package/esm/components/search/Component.js +1 -1
- package/esm/components/search/index.css +2 -2
- package/esm/components/virtual-options-list/Component.js +1 -1
- package/esm/components/virtual-options-list/index.css +20 -19
- package/esm/{list-popover-desktop-446b6d5f.js → list-popover-desktop-e4b69ce0.js} +1 -1
- package/esm/mobile/Component.mobile.js +1 -1
- package/esm/mobile.module-a3e68caf.js +4 -0
- package/esm/presets/index.js +1 -1
- package/esm/presets/useSelectWithApply/hook.js +1 -1
- package/esm/presets/useSelectWithApply/options-list-with-apply/Component.js +1 -1
- package/esm/presets/useSelectWithApply/options-list-with-apply/footer/Component.js +1 -1
- package/esm/presets/useSelectWithApply/options-list-with-apply/footer/index.css +6 -4
- package/esm/presets/useSelectWithApply/options-list-with-apply/header/Component.js +1 -1
- package/esm/presets/useSelectWithApply/options-list-with-apply/header/index.css +3 -3
- package/esm/presets/useSelectWithApply/options-list-with-apply/index.d.ts +1 -1
- package/esm/presets/useSelectWithApply/options-list-with-apply/index.js +1 -1
- package/esm/presets/useSelectWithLoading/hook.js +1 -1
- package/esm/presets/useSelectWithLoading/index.css +2 -2
- package/esm/shared/index.js +1 -1
- package/esm/utils.d.ts +1 -1
- package/esm/utils.js +13 -2
- package/{list-popover-desktop-6bae9b47.js → list-popover-desktop-8ffefe6e.js} +1 -1
- package/mobile/Component.mobile.js +1 -1
- package/mobile.module-97d68ba9.js +6 -0
- package/modern/components/arrow/Component.js +1 -1
- package/modern/components/arrow/index.css +3 -3
- package/modern/components/base-checkmark/Component.js +1 -1
- package/modern/components/base-checkmark/index.css +6 -6
- package/modern/components/base-option/Component.js +1 -1
- package/modern/components/base-option/index.css +18 -17
- package/modern/components/base-select/Component.js +2 -2
- package/modern/components/base-select/components/list-desktop/list-popover-desktop.js +1 -1
- package/modern/components/base-select/components/list-mobile/list-bottom-sheet-mobile.js +1 -1
- package/modern/components/base-select/components/list-mobile/list-modal-mobile.js +1 -1
- package/modern/components/base-select/index.css +24 -22
- package/modern/components/base-select/mobile.css +16 -15
- package/modern/components/checkmark/Component.js +1 -1
- package/modern/components/checkmark/index.css +12 -11
- package/modern/components/checkmark-mobile/Component.js +1 -1
- package/modern/components/checkmark-mobile/index.css +6 -6
- package/modern/components/clear-button/Component.js +1 -1
- package/modern/components/clear-button/index.css +6 -6
- package/modern/components/field/Component.js +1 -1
- package/modern/components/field/index.css +12 -12
- package/modern/components/footer/Component.js +1 -1
- package/modern/components/footer/index.css +5 -5
- package/modern/components/optgroup/Component.js +1 -1
- package/modern/components/optgroup/index.css +6 -6
- package/modern/components/option/Component.js +1 -1
- package/modern/components/option/index.css +21 -21
- package/modern/components/options-list/Component.js +3 -3
- package/modern/components/options-list/index.css +14 -11
- package/modern/components/search/Component.js +1 -1
- package/modern/components/search/index.css +2 -2
- package/modern/components/virtual-options-list/Component.js +1 -1
- package/modern/components/virtual-options-list/index.css +20 -19
- package/modern/{list-popover-desktop-46e08681.js → list-popover-desktop-85370c2c.js} +1 -1
- package/modern/mobile/Component.mobile.js +1 -1
- package/modern/mobile.module-eb08a4de.js +4 -0
- package/modern/presets/index.js +1 -1
- package/modern/presets/useSelectWithApply/hook.js +1 -1
- package/modern/presets/useSelectWithApply/options-list-with-apply/Component.js +1 -1
- package/modern/presets/useSelectWithApply/options-list-with-apply/footer/Component.js +1 -1
- package/modern/presets/useSelectWithApply/options-list-with-apply/footer/index.css +6 -4
- package/modern/presets/useSelectWithApply/options-list-with-apply/header/Component.js +1 -1
- package/modern/presets/useSelectWithApply/options-list-with-apply/header/index.css +3 -3
- package/modern/presets/useSelectWithApply/options-list-with-apply/index.d.ts +1 -1
- package/modern/presets/useSelectWithApply/options-list-with-apply/index.js +1 -1
- package/modern/presets/useSelectWithLoading/hook.js +1 -1
- package/modern/presets/useSelectWithLoading/index.css +2 -2
- package/modern/shared/index.js +1 -1
- package/modern/utils.d.ts +1 -1
- package/modern/utils.js +13 -2
- package/moderncssm/Component.responsive.d.ts +7 -0
- package/moderncssm/Component.responsive.js +21 -0
- package/moderncssm/components/arrow/Component.d.ts +5 -0
- package/moderncssm/components/arrow/Component.js +8 -0
- package/moderncssm/components/arrow/index.d.ts +1 -0
- package/moderncssm/components/arrow/index.js +1 -0
- package/moderncssm/components/arrow/index.module.css +23 -0
- package/moderncssm/components/base-checkmark/Component.d.ts +5 -0
- package/moderncssm/components/base-checkmark/Component.js +15 -0
- package/moderncssm/components/base-checkmark/index.d.ts +1 -0
- package/moderncssm/components/base-checkmark/index.js +1 -0
- package/moderncssm/components/base-checkmark/index.module.css +30 -0
- package/moderncssm/components/base-option/Component.d.ts +4 -0
- package/moderncssm/components/base-option/Component.js +33 -0
- package/moderncssm/components/base-option/index.d.ts +1 -0
- package/moderncssm/components/base-option/index.js +1 -0
- package/moderncssm/components/base-option/index.module.css +81 -0
- package/moderncssm/components/base-select/Component.d.ts +14 -0
- package/moderncssm/components/base-select/Component.js +408 -0
- package/moderncssm/components/base-select/components/list-desktop/helpers/get-list-popover-desktop-props.d.ts +12 -0
- package/moderncssm/components/base-select/components/list-desktop/helpers/get-list-popover-desktop-props.js +15 -0
- package/moderncssm/components/base-select/components/list-desktop/list-popover-desktop.d.ts +9 -0
- package/moderncssm/components/base-select/components/list-desktop/list-popover-desktop.js +13 -0
- package/moderncssm/components/base-select/components/list-desktop/types/types.d.ts +3 -0
- package/moderncssm/components/base-select/components/list-desktop/types/types.js +1 -0
- package/moderncssm/components/base-select/components/list-mobile/helpers/get-list-bottom-sheet-mobile-props.d.ts +16 -0
- package/moderncssm/components/base-select/components/list-mobile/helpers/get-list-bottom-sheet-mobile-props.js +19 -0
- package/moderncssm/components/base-select/components/list-mobile/helpers/get-list-modal-mobile-props.d.ts +28 -0
- package/moderncssm/components/base-select/components/list-mobile/helpers/get-list-modal-mobile-props.js +18 -0
- package/moderncssm/components/base-select/components/list-mobile/helpers/index.d.ts +2 -0
- package/moderncssm/components/base-select/components/list-mobile/helpers/index.js +2 -0
- package/moderncssm/components/base-select/components/list-mobile/list-bottom-sheet-mobile.d.ts +15 -0
- package/moderncssm/components/base-select/components/list-mobile/list-bottom-sheet-mobile.js +24 -0
- package/moderncssm/components/base-select/components/list-mobile/list-mobile.d.ts +16 -0
- package/moderncssm/components/base-select/components/list-mobile/list-mobile.js +17 -0
- package/moderncssm/components/base-select/components/list-mobile/list-modal-mobile.d.ts +15 -0
- package/moderncssm/components/base-select/components/list-mobile/list-modal-mobile.js +32 -0
- package/moderncssm/components/base-select/components/list-mobile/types/types.d.ts +4 -0
- package/moderncssm/components/base-select/components/list-mobile/types/types.js +1 -0
- package/moderncssm/components/base-select/index.d.ts +1 -0
- package/moderncssm/components/base-select/index.js +1 -0
- package/moderncssm/components/base-select/index.module.css +81 -0
- package/moderncssm/components/base-select/mobile.module.css +48 -0
- package/moderncssm/components/base-select/types/component-types.d.ts +50 -0
- package/moderncssm/components/base-select/types/component-types.js +1 -0
- package/moderncssm/components/checkmark/Component.d.ts +5 -0
- package/moderncssm/components/checkmark/Component.js +20 -0
- package/moderncssm/components/checkmark/index.d.ts +1 -0
- package/moderncssm/components/checkmark/index.js +1 -0
- package/moderncssm/components/checkmark/index.module.css +59 -0
- package/moderncssm/components/checkmark-mobile/Component.d.ts +5 -0
- package/moderncssm/components/checkmark-mobile/Component.js +11 -0
- package/moderncssm/components/checkmark-mobile/index.d.ts +1 -0
- package/moderncssm/components/checkmark-mobile/index.js +1 -0
- package/moderncssm/components/checkmark-mobile/index.module.css +34 -0
- package/moderncssm/components/clear-button/Component.d.ts +5 -0
- package/moderncssm/components/clear-button/Component.js +9 -0
- package/moderncssm/components/clear-button/index.d.ts +1 -0
- package/moderncssm/components/clear-button/index.js +1 -0
- package/moderncssm/components/clear-button/index.module.css +47 -0
- package/moderncssm/components/field/Component.d.ts +13 -0
- package/moderncssm/components/field/Component.js +35 -0
- package/moderncssm/components/field/index.d.ts +1 -0
- package/moderncssm/components/field/index.js +1 -0
- package/moderncssm/components/field/index.module.css +74 -0
- package/moderncssm/components/footer/Component.d.ts +12 -0
- package/moderncssm/components/footer/Component.js +22 -0
- package/moderncssm/components/footer/index.d.ts +1 -0
- package/moderncssm/components/footer/index.js +1 -0
- package/moderncssm/components/footer/index.module.css +28 -0
- package/moderncssm/components/index.d.ts +9 -0
- package/moderncssm/components/index.js +9 -0
- package/moderncssm/components/native-select/Component.d.ts +25 -0
- package/moderncssm/components/native-select/Component.js +13 -0
- package/moderncssm/components/native-select/index.d.ts +1 -0
- package/moderncssm/components/native-select/index.js +1 -0
- package/moderncssm/components/optgroup/Component.d.ts +5 -0
- package/moderncssm/components/optgroup/Component.js +11 -0
- package/moderncssm/components/optgroup/index.d.ts +1 -0
- package/moderncssm/components/optgroup/index.js +1 -0
- package/moderncssm/components/optgroup/index.module.css +46 -0
- package/moderncssm/components/option/Component.d.ts +4 -0
- package/moderncssm/components/option/Component.js +23 -0
- package/moderncssm/components/option/index.d.ts +1 -0
- package/moderncssm/components/option/index.js +1 -0
- package/moderncssm/components/option/index.module.css +110 -0
- package/moderncssm/components/options-list/Component.d.ts +5 -0
- package/moderncssm/components/options-list/Component.js +88 -0
- package/moderncssm/components/options-list/index.d.ts +1 -0
- package/moderncssm/components/options-list/index.js +1 -0
- package/moderncssm/components/options-list/index.module.css +51 -0
- package/moderncssm/components/search/Component.d.ts +5 -0
- package/moderncssm/components/search/Component.js +9 -0
- package/moderncssm/components/search/index.d.ts +1 -0
- package/moderncssm/components/search/index.js +1 -0
- package/moderncssm/components/search/index.module.css +14 -0
- package/moderncssm/components/virtual-options-list/Component.d.ts +5 -0
- package/moderncssm/components/virtual-options-list/Component.js +138 -0
- package/moderncssm/components/virtual-options-list/index.d.ts +1 -0
- package/moderncssm/components/virtual-options-list/index.js +1 -0
- package/moderncssm/components/virtual-options-list/index.module.css +79 -0
- package/moderncssm/consts.d.ts +12 -0
- package/moderncssm/consts.js +13 -0
- package/moderncssm/desktop/Component.desktop.d.ts +6 -0
- package/moderncssm/desktop/Component.desktop.js +17 -0
- package/moderncssm/desktop/index.d.ts +2 -0
- package/moderncssm/desktop/index.js +1 -0
- package/moderncssm/hook-8c561f14.d.ts +115 -0
- package/moderncssm/hook-a8bc7fe8.d.ts +17 -0
- package/moderncssm/hook-a8bc7fe8.js +169 -0
- package/moderncssm/index.d.ts +2 -0
- package/moderncssm/index.js +1 -0
- package/moderncssm/mobile/Component.mobile.d.ts +5 -0
- package/moderncssm/mobile/Component.mobile.js +54 -0
- package/moderncssm/mobile/Component.modal.mobile.d.ts +4 -0
- package/moderncssm/mobile/Component.modal.mobile.js +6 -0
- package/moderncssm/mobile/index.d.ts +3 -0
- package/moderncssm/mobile/index.js +2 -0
- package/moderncssm/presets/index.d.ts +3 -0
- package/moderncssm/presets/index.js +3 -0
- package/moderncssm/presets/useLazyLoading/hook.d.ts +48 -0
- package/moderncssm/presets/useLazyLoading/hook.js +215 -0
- package/moderncssm/presets/useSelectWithApply/hook.d.ts +0 -0
- package/moderncssm/presets/useSelectWithApply/hook.js +4 -0
- package/moderncssm/presets/useSelectWithApply/options-list-with-apply/Component.d.ts +0 -0
- package/moderncssm/presets/useSelectWithApply/options-list-with-apply/Component.js +6 -0
- package/moderncssm/presets/useSelectWithApply/options-list-with-apply/footer/Component.d.ts +12 -0
- package/moderncssm/presets/useSelectWithApply/options-list-with-apply/footer/Component.js +12 -0
- package/moderncssm/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css +12 -0
- package/moderncssm/presets/useSelectWithApply/options-list-with-apply/footer/vars.css +0 -0
- package/moderncssm/presets/useSelectWithApply/options-list-with-apply/header/Component.d.ts +11 -0
- package/moderncssm/presets/useSelectWithApply/options-list-with-apply/header/Component.js +9 -0
- package/moderncssm/presets/useSelectWithApply/options-list-with-apply/header/index.module.css +9 -0
- package/moderncssm/presets/useSelectWithApply/options-list-with-apply/index.d.ts +1 -0
- package/moderncssm/presets/useSelectWithApply/options-list-with-apply/index.js +1 -0
- package/moderncssm/presets/useSelectWithLoading/hook.d.ts +13 -0
- package/moderncssm/presets/useSelectWithLoading/hook.js +23 -0
- package/moderncssm/presets/useSelectWithLoading/index.module.css +7 -0
- package/moderncssm/shared/index.d.ts +13 -0
- package/moderncssm/shared/index.js +14 -0
- package/moderncssm/typings.d.ts +744 -0
- package/moderncssm/typings.js +1 -0
- package/moderncssm/utils.d.ts +81 -0
- package/moderncssm/utils.js +184 -0
- package/moderncssm/vars.css +10 -0
- package/package.json +15 -15
- package/presets/index.js +1 -1
- package/presets/useSelectWithApply/hook.js +1 -1
- package/presets/useSelectWithApply/options-list-with-apply/Component.js +1 -1
- package/presets/useSelectWithApply/options-list-with-apply/footer/Component.js +1 -1
- package/presets/useSelectWithApply/options-list-with-apply/footer/index.css +6 -4
- package/presets/useSelectWithApply/options-list-with-apply/header/Component.js +1 -1
- package/presets/useSelectWithApply/options-list-with-apply/header/index.css +3 -3
- package/presets/useSelectWithApply/options-list-with-apply/index.d.ts +1 -1
- package/presets/useSelectWithApply/options-list-with-apply/index.js +1 -1
- package/presets/useSelectWithLoading/hook.js +1 -1
- package/presets/useSelectWithLoading/index.css +2 -2
- package/shared/index.js +1 -1
- package/src/components/arrow/index.module.css +1 -1
- package/src/components/base-checkmark/index.module.css +1 -1
- package/src/components/base-option/index.module.css +3 -3
- package/src/components/base-select/index.module.css +9 -9
- package/src/components/base-select/mobile.module.css +4 -4
- package/src/components/checkmark/index.module.css +1 -1
- package/src/components/checkmark-mobile/index.module.css +1 -1
- package/src/components/field/index.module.css +1 -1
- package/src/components/footer/index.module.css +1 -1
- package/src/components/optgroup/index.module.css +1 -1
- package/src/components/option/index.module.css +2 -3
- package/src/components/options-list/Component.tsx +2 -1
- package/src/components/options-list/index.module.css +6 -2
- package/src/components/search/index.module.css +1 -1
- package/src/components/virtual-options-list/index.module.css +5 -5
- package/src/presets/useSelectWithApply/options-list-with-apply/footer/index.module.css +3 -2
- package/src/presets/useSelectWithApply/options-list-with-apply/footer/vars.css +3 -0
- package/src/presets/useSelectWithApply/options-list-with-apply/header/index.module.css +1 -1
- package/src/utils.ts +28 -3
- package/src/vars.css +4 -4
- package/utils.d.ts +1 -1
- package/utils.js +11 -0
- package/esm/mobile.module-eaf56278.js +0 -4
- package/mobile.module-8d14caac.js +0 -6
- package/modern/mobile.module-2f7796c1.js +0 -4
- /package/esm/{hook-570b8ac7.d.ts → hook-276c96dc.d.ts} +0 -0
- /package/esm/{hook-570b8ac7.js → hook-276c96dc.js} +0 -0
- /package/esm/{list-popover-desktop-446b6d5f.d.ts → list-popover-desktop-e4b69ce0.d.ts} +0 -0
- /package/{hook-a71861cb.d.ts → hook-c8ba558c.d.ts} +0 -0
- /package/{hook-a71861cb.js → hook-c8ba558c.js} +0 -0
- /package/{list-popover-desktop-6bae9b47.d.ts → list-popover-desktop-8ffefe6e.d.ts} +0 -0
- /package/modern/{hook-0b565ee2.d.ts → hook-a054f3bb.d.ts} +0 -0
- /package/modern/{hook-0b565ee2.js → hook-a054f3bb.js} +0 -0
- /package/modern/{list-popover-desktop-46e08681.d.ts → list-popover-desktop-85370c2c.d.ts} +0 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import React, { forwardRef, useRef, useState, useEffect, useMemo } from 'react';
|
|
2
|
+
import mergeRefs from 'react-merge-refs';
|
|
3
|
+
import { useVirtual } from 'react-virtual';
|
|
4
|
+
import cn from 'classnames';
|
|
5
|
+
import { useMatchMedia } from '@alfalab/core-components-mq/moderncssm';
|
|
6
|
+
import { Scrollbar } from '@alfalab/core-components-scrollbar/moderncssm';
|
|
7
|
+
import { isClient } from '@alfalab/core-components-shared/moderncssm';
|
|
8
|
+
import { SIZE_TO_CLASSNAME_MAP, DEFAULT_VISIBLE_OPTIONS } from '../../consts.js';
|
|
9
|
+
import { usePrevious, lastIndexOf, useVisibleOptions, isGroup } from '../../utils.js';
|
|
10
|
+
import { Optgroup } from '../optgroup/Component.js';
|
|
11
|
+
import styles from './index.module.css';
|
|
12
|
+
|
|
13
|
+
const VirtualOptionsList = forwardRef(({ size = 48, flatOptions = [], highlightedIndex = -1, optionGroupClassName, className, getOptionProps, groupOptionProps = {}, Option, open, options = [], Optgroup: Optgroup$1 = Optgroup, dataTestId, emptyPlaceholder, visibleOptions = DEFAULT_VISIBLE_OPTIONS, header, footer, showFooter = true, optionsListWidth, onScroll, nativeScrollbar: nativeScrollbarProp, setHighlightedIndex, selectedItems, setSelectedItems, search, multiple, }, ref) => {
|
|
14
|
+
const listRef = useRef(null);
|
|
15
|
+
const parentRef = useRef(null);
|
|
16
|
+
const scrollbarRef = useRef(null);
|
|
17
|
+
const [visibleOptionsInvalidateKey, setVisibleOptionsInvalidateKey] = useState('');
|
|
18
|
+
const prevHighlightedIndex = usePrevious(highlightedIndex) || -1;
|
|
19
|
+
const query = '(max-width: 1023px)';
|
|
20
|
+
let [nativeScrollbar] = useMatchMedia(query, () => isClient() ? window.matchMedia(query).matches : true);
|
|
21
|
+
const rowVirtualizer = useVirtual({
|
|
22
|
+
size: flatOptions.length,
|
|
23
|
+
parentRef: (ref || parentRef),
|
|
24
|
+
overscan: 15,
|
|
25
|
+
});
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
27
|
+
nativeScrollbar = Boolean(nativeScrollbarProp ?? nativeScrollbar);
|
|
28
|
+
// Сколл к выбранному пункту при открытии меню
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (open) {
|
|
31
|
+
rowVirtualizer.scrollToIndex(highlightedIndex, { align: 'end' });
|
|
32
|
+
}
|
|
33
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
34
|
+
}, [open]);
|
|
35
|
+
// Скролл к пункту, которого нет на экране
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (highlightedIndex === -1)
|
|
38
|
+
return;
|
|
39
|
+
if (!rowVirtualizer.virtualItems.some((option) => option.index === highlightedIndex)) {
|
|
40
|
+
rowVirtualizer.scrollToIndex(highlightedIndex, { align: 'end' });
|
|
41
|
+
}
|
|
42
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
43
|
+
}, [highlightedIndex]);
|
|
44
|
+
// Циклическая навигация
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
const notDisabled = (option) => !option.disabled;
|
|
47
|
+
const firstNonDisabled = flatOptions.findIndex(notDisabled);
|
|
48
|
+
const lastNonDisabled = lastIndexOf(flatOptions, notDisabled);
|
|
49
|
+
if (prevHighlightedIndex <= firstNonDisabled &&
|
|
50
|
+
highlightedIndex === flatOptions.length - 1) {
|
|
51
|
+
rowVirtualizer.scrollToIndex(lastNonDisabled);
|
|
52
|
+
}
|
|
53
|
+
if (prevHighlightedIndex >= lastNonDisabled && highlightedIndex === 0) {
|
|
54
|
+
rowVirtualizer.scrollToIndex(0);
|
|
55
|
+
}
|
|
56
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
57
|
+
}, [prevHighlightedIndex, highlightedIndex]);
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
setVisibleOptionsInvalidateKey(
|
|
60
|
+
/**
|
|
61
|
+
* react-virtual может несколько раз отрендерить список с одним элементом,
|
|
62
|
+
* поэтому нужно еще раз пересчитать высоту, когда список ВИДИМЫХ пунктов будет отрендерен полностью
|
|
63
|
+
* Также, высоту нужно пересчитывать при изменении пунктов меню
|
|
64
|
+
*/
|
|
65
|
+
rowVirtualizer.virtualItems
|
|
66
|
+
.slice(0, Math.min(rowVirtualizer.virtualItems.length, visibleOptions + 1))
|
|
67
|
+
.map((item) => flatOptions[item.index].key)
|
|
68
|
+
.join('_'));
|
|
69
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
70
|
+
}, [rowVirtualizer.virtualItems.length, flatOptions]);
|
|
71
|
+
useVisibleOptions({
|
|
72
|
+
visibleOptions,
|
|
73
|
+
invalidate: visibleOptionsInvalidateKey,
|
|
74
|
+
listRef,
|
|
75
|
+
styleTargetRef: nativeScrollbar ? parentRef : scrollbarRef,
|
|
76
|
+
open,
|
|
77
|
+
});
|
|
78
|
+
// Т.к. рендерится плоский список, необходимо знать индекс, когда начинается новая группа
|
|
79
|
+
const groupStartIndexes = useMemo(() => {
|
|
80
|
+
let currentIndex = 0;
|
|
81
|
+
return options.reduce((acc, option, index) => {
|
|
82
|
+
if (isGroup(option)) {
|
|
83
|
+
acc[currentIndex] = index;
|
|
84
|
+
currentIndex += option.options.length;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
currentIndex += 1;
|
|
88
|
+
}
|
|
89
|
+
return acc;
|
|
90
|
+
}, {});
|
|
91
|
+
}, [options]);
|
|
92
|
+
const renderList = () => rowVirtualizer.virtualItems.map((virtualRow) => {
|
|
93
|
+
const option = flatOptions[virtualRow.index];
|
|
94
|
+
const renderGroup = () => {
|
|
95
|
+
const group = options[groupStartIndexes[virtualRow.index]];
|
|
96
|
+
if (!group)
|
|
97
|
+
return null;
|
|
98
|
+
const groupSelectedItems = selectedItems?.filter((item) => group.options.includes(item));
|
|
99
|
+
const handleSelectedItems = (items) => {
|
|
100
|
+
setSelectedItems((selectedItems?.filter((item) => !group.options.includes(item)) ?? []).concat(items));
|
|
101
|
+
};
|
|
102
|
+
return (React.createElement(Optgroup$1, { label: group.label, size: size, className: optionGroupClassName, options: group.options, selectedItems: groupSelectedItems, setSelectedItems: handleSelectedItems, search: search, multiple: multiple, ...groupOptionProps }));
|
|
103
|
+
};
|
|
104
|
+
return (React.createElement("div", { key: virtualRow.index, ref: virtualRow.measureRef, className: cn(styles.virtualRow, {
|
|
105
|
+
[styles.highlighted]: highlightedIndex === virtualRow.index,
|
|
106
|
+
}), style: {
|
|
107
|
+
transform: `translateY(${virtualRow.start}px)`,
|
|
108
|
+
} },
|
|
109
|
+
renderGroup(),
|
|
110
|
+
!isGroup(option) && (React.createElement(Option, { ...getOptionProps(option, virtualRow.index) }))));
|
|
111
|
+
});
|
|
112
|
+
const contentNodeProps = {
|
|
113
|
+
className: styles.inner,
|
|
114
|
+
style: { height: `${rowVirtualizer.totalSize}px` },
|
|
115
|
+
ref: listRef,
|
|
116
|
+
};
|
|
117
|
+
const renderWithCustomScrollbar = () => (React.createElement(Scrollbar, { className: styles.scrollable, ref: scrollbarRef, horizontalAutoStretch: optionsListWidth === 'content', scrollableNodeProps: { onScroll, ref: parentRef }, contentNodeProps: contentNodeProps }, renderList()));
|
|
118
|
+
const renderWithNativeScrollbar = () => {
|
|
119
|
+
if (visibleOptions) {
|
|
120
|
+
return (React.createElement("div", { className: styles.scrollable, ref: mergeRefs([parentRef, ref]), onScroll: onScroll },
|
|
121
|
+
React.createElement("div", { ...contentNodeProps }, renderList())));
|
|
122
|
+
}
|
|
123
|
+
return React.createElement("div", { ...contentNodeProps }, renderList());
|
|
124
|
+
};
|
|
125
|
+
const resetHighlightedIndex = () => setHighlightedIndex?.(-1);
|
|
126
|
+
if (options.length === 0 && !emptyPlaceholder) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
return (React.createElement("div", { className: cn(styles.virtualOptionsList, styles[SIZE_TO_CLASSNAME_MAP[size]], className), "data-test-id": dataTestId },
|
|
130
|
+
header && (React.createElement("div", { className: styles.virtualOptionsListHeader, onMouseEnter: resetHighlightedIndex }, header)),
|
|
131
|
+
nativeScrollbar ? renderWithNativeScrollbar() : renderWithCustomScrollbar(),
|
|
132
|
+
emptyPlaceholder && options.length === 0 && (React.createElement("div", { className: styles.emptyPlaceholder }, emptyPlaceholder)),
|
|
133
|
+
showFooter && footer && (React.createElement("div", { onMouseEnter: resetHighlightedIndex, className: cn(styles.virtualOptionsListFooter, {
|
|
134
|
+
[styles.withBorder]: visibleOptions && flatOptions.length > visibleOptions,
|
|
135
|
+
}) }, footer))));
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
export { VirtualOptionsList };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Component";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { VirtualOptionsList } from './Component.js';
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/* */
|
|
2
|
+
:root {
|
|
3
|
+
|
|
4
|
+
/* options list */
|
|
5
|
+
--select-options-list-empty-placeholder-color: var(--color-light-text-secondary);
|
|
6
|
+
--select-option-divider-display: none;
|
|
7
|
+
--select-option-divider-background: var(--color-light-neutral-400);
|
|
8
|
+
|
|
9
|
+
/* option */
|
|
10
|
+
|
|
11
|
+
--select-option-left-padding: var(--gap-12);
|
|
12
|
+
--select-option-right-padding: var(--gap-12);
|
|
13
|
+
|
|
14
|
+
/* checkmark */
|
|
15
|
+
|
|
16
|
+
/* optgroup */
|
|
17
|
+
}
|
|
18
|
+
.virtualOptionsList {
|
|
19
|
+
width: 100%;
|
|
20
|
+
outline: none;
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
position: sticky;
|
|
23
|
+
justify-content: space-between;
|
|
24
|
+
}
|
|
25
|
+
.virtualOptionsListHeader {
|
|
26
|
+
box-sizing: border-box;
|
|
27
|
+
border-bottom: 1px solid var(--color-light-neutral-300);
|
|
28
|
+
}
|
|
29
|
+
.virtualOptionsListFooter {
|
|
30
|
+
position: sticky;
|
|
31
|
+
bottom: var(--gap-0);
|
|
32
|
+
box-sizing: border-box;
|
|
33
|
+
border-top: 1px solid transparent
|
|
34
|
+
}
|
|
35
|
+
.virtualOptionsListFooter.withBorder {
|
|
36
|
+
border-top: 1px solid var(--color-light-neutral-300);
|
|
37
|
+
}
|
|
38
|
+
.scrollable {
|
|
39
|
+
position: relative;
|
|
40
|
+
overflow: auto;
|
|
41
|
+
width: 100%;
|
|
42
|
+
}
|
|
43
|
+
.inner {
|
|
44
|
+
position: relative;
|
|
45
|
+
width: 100%;
|
|
46
|
+
}
|
|
47
|
+
.virtualRow {
|
|
48
|
+
position: absolute;
|
|
49
|
+
top: var(--gap-0);
|
|
50
|
+
left: var(--gap-0);
|
|
51
|
+
width: 100%
|
|
52
|
+
}
|
|
53
|
+
.virtualRow:before {
|
|
54
|
+
content: '';
|
|
55
|
+
position: absolute;
|
|
56
|
+
z-index: 1;
|
|
57
|
+
left: var(--select-option-left-padding);
|
|
58
|
+
right: var(--select-option-right-padding);
|
|
59
|
+
top: var(--gap-0);
|
|
60
|
+
height: 1px;
|
|
61
|
+
background: var(--select-option-divider-background);
|
|
62
|
+
display: var(--select-option-divider-display);
|
|
63
|
+
}
|
|
64
|
+
.virtualRow:first-child:before {
|
|
65
|
+
display: none;
|
|
66
|
+
}
|
|
67
|
+
.highlighted:before,
|
|
68
|
+
.highlighted + .virtualRow:before {
|
|
69
|
+
display: none;
|
|
70
|
+
}
|
|
71
|
+
.emptyPlaceholder {
|
|
72
|
+
padding: var(--gap-16) var(--gap-12);
|
|
73
|
+
color: var(--select-options-list-empty-placeholder-color);
|
|
74
|
+
flex: 1;
|
|
75
|
+
}
|
|
76
|
+
.size-64 .emptyPlaceholder,
|
|
77
|
+
.size-72 .emptyPlaceholder {
|
|
78
|
+
padding: var(--gap-24) var(--gap-16);
|
|
79
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
declare const DEFAULT_VISIBLE_OPTIONS = 5;
|
|
2
|
+
declare const SIZE_TO_CLASSNAME_MAP: {
|
|
3
|
+
s: string;
|
|
4
|
+
m: string;
|
|
5
|
+
l: string;
|
|
6
|
+
xl: string;
|
|
7
|
+
48: string;
|
|
8
|
+
56: string;
|
|
9
|
+
64: string;
|
|
10
|
+
72: string;
|
|
11
|
+
};
|
|
12
|
+
export { DEFAULT_VISIBLE_OPTIONS, SIZE_TO_CLASSNAME_MAP };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const DEFAULT_VISIBLE_OPTIONS = 5;
|
|
2
|
+
const SIZE_TO_CLASSNAME_MAP = {
|
|
3
|
+
s: 'size-48',
|
|
4
|
+
m: 'size-56',
|
|
5
|
+
l: 'size-64',
|
|
6
|
+
xl: 'size-72',
|
|
7
|
+
48: 'size-48',
|
|
8
|
+
56: 'size-56',
|
|
9
|
+
64: 'size-64',
|
|
10
|
+
72: 'size-72',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export { DEFAULT_VISIBLE_OPTIONS, SIZE_TO_CLASSNAME_MAP };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import React from 'react';
|
|
3
|
+
declare const SelectDesktop: React.ForwardRefExoticComponent<Omit<import("../typings").BaseSelectProps, "fieldProps"> & {
|
|
4
|
+
fieldProps?: import("../typings").SelectFieldProps | undefined;
|
|
5
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
6
|
+
export { SelectDesktop };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { FormControlDesktop } from '@alfalab/core-components-form-control/moderncssm/desktop';
|
|
3
|
+
import { Popover } from '@alfalab/core-components-popover/moderncssm';
|
|
4
|
+
import { Arrow } from '../components/arrow/Component.js';
|
|
5
|
+
import { BaseSelect } from '../components/base-select/Component.js';
|
|
6
|
+
import { Field } from '../components/field/Component.js';
|
|
7
|
+
import { Optgroup } from '../components/optgroup/Component.js';
|
|
8
|
+
import { Option } from '../components/option/Component.js';
|
|
9
|
+
import { OptionsList } from '../components/options-list/Component.js';
|
|
10
|
+
import { Search } from '../components/search/Component.js';
|
|
11
|
+
|
|
12
|
+
const SelectDesktop = forwardRef(({ Arrow: Arrow$1 = Arrow, Field: Field$1 = Field, OptionsList: OptionsList$1 = OptionsList, Optgroup: Optgroup$1 = Optgroup, Option: Option$1 = Option, Search: Search$1 = Search, fieldProps = {}, ...restProps }, ref) => (React.createElement(BaseSelect, { ref: ref, view: 'desktop', Option: Option$1, Field: Field$1, fieldProps: {
|
|
13
|
+
FormControlComponent: FormControlDesktop,
|
|
14
|
+
...fieldProps,
|
|
15
|
+
}, Search: Search$1, Optgroup: Optgroup$1, OptionsList: OptionsList$1, Arrow: Arrow$1, Popover: Popover, ...restProps })));
|
|
16
|
+
|
|
17
|
+
export { SelectDesktop };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SelectDesktop } from './Component.desktop.js';
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { BaseSelectProps, OptionShape } from "./typings";
|
|
3
|
+
type UseSelectWithApplyProps = {
|
|
4
|
+
/**
|
|
5
|
+
* Список выбранных пунктов
|
|
6
|
+
*/
|
|
7
|
+
selected: BaseSelectProps['selected'];
|
|
8
|
+
/**
|
|
9
|
+
* Список вариантов выбора
|
|
10
|
+
*/
|
|
11
|
+
options: BaseSelectProps['options'];
|
|
12
|
+
/**
|
|
13
|
+
* Обработчик выбора
|
|
14
|
+
*/
|
|
15
|
+
onChange: BaseSelectProps['onChange'];
|
|
16
|
+
/**
|
|
17
|
+
* Компонент выпадающего меню
|
|
18
|
+
*/
|
|
19
|
+
OptionsList?: BaseSelectProps['OptionsList'];
|
|
20
|
+
/**
|
|
21
|
+
* Пропсы, которые будут прокинуты в компонент списка
|
|
22
|
+
*/
|
|
23
|
+
optionsListProps?: BaseSelectProps['optionsListProps'];
|
|
24
|
+
/**
|
|
25
|
+
* Включает отображение поиска
|
|
26
|
+
*/
|
|
27
|
+
showSearch?: BaseSelectProps['showSearch'];
|
|
28
|
+
/**
|
|
29
|
+
* Настройки поиска
|
|
30
|
+
*/
|
|
31
|
+
searchProps?: BaseSelectProps['searchProps'];
|
|
32
|
+
/**
|
|
33
|
+
* Показывать кнопку очистки
|
|
34
|
+
*/
|
|
35
|
+
showClear?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Показывать пункт "Выбрать все"
|
|
38
|
+
*/
|
|
39
|
+
showSelectAll?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Показывать пункт "Выбрать все" в заголовке списка
|
|
42
|
+
*/
|
|
43
|
+
showHeaderWithSelectAll?: boolean;
|
|
44
|
+
};
|
|
45
|
+
declare const SELECT_ALL_KEY = "select_all";
|
|
46
|
+
declare function useSelectWithApply({ options, selected, onChange, OptionsList, optionsListProps, showClear, showSelectAll, showHeaderWithSelectAll, showSearch, searchProps, }: UseSelectWithApplyProps): {
|
|
47
|
+
OptionsList: import("react").ForwardRefExoticComponent<import("./typings").OptionsListProps & {
|
|
48
|
+
showClear?: boolean | undefined;
|
|
49
|
+
onClose?: (() => void) | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Обработчик выбора
|
|
52
|
+
*/
|
|
53
|
+
selectedDraft?: OptionShape[] | undefined;
|
|
54
|
+
OptionsList?: import("react").FC<import("./typings").OptionsListProps & import("react").RefAttributes<HTMLDivElement>> | undefined;
|
|
55
|
+
Footer?: import("react").FC<import("./presets/useSelectWithApply/options-list-with-apply/footer/Component").FooterProps> | undefined;
|
|
56
|
+
Header?: import("react").FC<import("./presets/useSelectWithApply/options-list-with-apply/header/Component").HeaderProps> | undefined;
|
|
57
|
+
headerProps?: import("./presets/useSelectWithApply/options-list-with-apply/header/Component").HeaderProps | undefined;
|
|
58
|
+
showHeaderWithSelectAll?: boolean | undefined;
|
|
59
|
+
setSelectedDraft?: ((selectedDraft: OptionShape[]) => void) | undefined;
|
|
60
|
+
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
61
|
+
optionsListProps: {
|
|
62
|
+
OptionsList: import("react").ComponentType<import("./typings").OptionsListProps & import("react").RefAttributes<HTMLDivElement>> | undefined;
|
|
63
|
+
showClear: boolean;
|
|
64
|
+
onClear: () => void;
|
|
65
|
+
onApply: () => void;
|
|
66
|
+
onClose: () => void;
|
|
67
|
+
selectedDraft: OptionShape[];
|
|
68
|
+
setSelectedDraft: import("react").Dispatch<import("react").SetStateAction<OptionShape[]>>;
|
|
69
|
+
showHeaderWithSelectAll: boolean;
|
|
70
|
+
headerProps: {
|
|
71
|
+
indeterminate: boolean;
|
|
72
|
+
checked: boolean;
|
|
73
|
+
onChange: () => void;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
allowUnselect: boolean;
|
|
77
|
+
multiple: boolean;
|
|
78
|
+
options: (OptionShape | import("./typings").GroupShape | {
|
|
79
|
+
key: string;
|
|
80
|
+
content: string;
|
|
81
|
+
})[];
|
|
82
|
+
onChange: (payload: import("./typings").BaseSelectChangePayload) => void;
|
|
83
|
+
selected: string | OptionShape | (string | OptionShape)[] | null | undefined;
|
|
84
|
+
showSearch: boolean;
|
|
85
|
+
searchProps: {
|
|
86
|
+
value: string;
|
|
87
|
+
onChange: ((value: string) => void) | undefined;
|
|
88
|
+
componentProps?: import("./typings").SearchProps | undefined;
|
|
89
|
+
accessor?: ((option: OptionShape) => string) | undefined;
|
|
90
|
+
filterFn?: ((optionText: string, search: string) => boolean) | undefined;
|
|
91
|
+
filterGroup?: boolean | undefined;
|
|
92
|
+
groupAccessor?: ((group: import("./typings").GroupShape) => string | undefined) | undefined;
|
|
93
|
+
} | undefined;
|
|
94
|
+
originalProps: {
|
|
95
|
+
options: (OptionShape | import("./typings").GroupShape)[];
|
|
96
|
+
selected: string | OptionShape | (string | OptionShape)[] | null | undefined;
|
|
97
|
+
onChange: (payload: import("./typings").BaseSelectChangePayload) => void;
|
|
98
|
+
OptionsList: import("react").ComponentType<import("./typings").OptionsListProps & import("react").RefAttributes<HTMLDivElement>> | undefined;
|
|
99
|
+
optionsListProps: unknown;
|
|
100
|
+
showClear: boolean;
|
|
101
|
+
showSelectAll: boolean;
|
|
102
|
+
showHeaderWithSelectAll: boolean;
|
|
103
|
+
showSearch: boolean;
|
|
104
|
+
searchProps: {
|
|
105
|
+
componentProps?: import("./typings").SearchProps | undefined;
|
|
106
|
+
accessor?: ((option: OptionShape) => string) | undefined;
|
|
107
|
+
filterFn?: ((optionText: string, search: string) => boolean) | undefined;
|
|
108
|
+
value?: string | undefined;
|
|
109
|
+
onChange?: ((value: string) => void) | undefined;
|
|
110
|
+
filterGroup?: boolean | undefined;
|
|
111
|
+
groupAccessor?: ((group: import("./typings").GroupShape) => string | undefined) | undefined;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
export { UseSelectWithApplyProps, SELECT_ALL_KEY, useSelectWithApply };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { OptionShape, OptionsListProps } from "./typings";
|
|
4
|
+
import { FooterProps } from "./presets/useSelectWithApply/options-list-with-apply/footer/Component";
|
|
5
|
+
import { HeaderProps } from "./presets/useSelectWithApply/options-list-with-apply/header/Component";
|
|
6
|
+
declare const OptionsListWithApply: React.ForwardRefExoticComponent<OptionsListProps & {
|
|
7
|
+
showClear?: boolean | undefined;
|
|
8
|
+
onClose?: (() => void) | undefined;
|
|
9
|
+
selectedDraft?: OptionShape[] | undefined;
|
|
10
|
+
OptionsList?: React.FC<OptionsListProps & React.RefAttributes<HTMLDivElement>> | undefined;
|
|
11
|
+
Footer?: React.FC<FooterProps> | undefined;
|
|
12
|
+
Header?: React.FC<HeaderProps> | undefined;
|
|
13
|
+
headerProps?: HeaderProps | undefined;
|
|
14
|
+
showHeaderWithSelectAll?: boolean | undefined;
|
|
15
|
+
setSelectedDraft?: ((selectedDraft: OptionShape[]) => void) | undefined;
|
|
16
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
17
|
+
export { OptionsListWithApply };
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import React, { forwardRef, useCallback, useEffect, useState, useMemo, useRef } from 'react';
|
|
2
|
+
import deepEqual from 'deep-equal';
|
|
3
|
+
import { defaultAccessor, defaultFilterFn, defaultGroupAccessor, processOptions, isGroup } from './utils.js';
|
|
4
|
+
import { OptionsList } from './components/options-list/Component.js';
|
|
5
|
+
import { DEFAULT_VISIBLE_OPTIONS } from './consts.js';
|
|
6
|
+
import { Footer } from './presets/useSelectWithApply/options-list-with-apply/footer/Component.js';
|
|
7
|
+
import { Header } from './presets/useSelectWithApply/options-list-with-apply/header/Component.js';
|
|
8
|
+
|
|
9
|
+
const OptionsListWithApply = forwardRef(({ toggleMenu, getOptionProps: defaultGetOptionProps, showClear = true, showHeaderWithSelectAll, selectedDraft = [], flatOptions = [], OptionsList: OptionsList$1 = OptionsList, onApply = () => null, onClear = () => null, onClose = () => null, visibleOptions = DEFAULT_VISIBLE_OPTIONS, Footer: Footer$1 = Footer, Header: Header$1 = Header, header, headerProps, setSelectedDraft, ...restProps }, ref) => {
|
|
10
|
+
const getOptionProps = useCallback((option, index) => {
|
|
11
|
+
const optionProps = defaultGetOptionProps(option, index);
|
|
12
|
+
const selected = option.key === SELECT_ALL_KEY
|
|
13
|
+
? selectedDraft.length === flatOptions.length - 1
|
|
14
|
+
: selectedDraft.some(({ key }) => key === option.key);
|
|
15
|
+
return {
|
|
16
|
+
...optionProps,
|
|
17
|
+
selected,
|
|
18
|
+
};
|
|
19
|
+
}, [defaultGetOptionProps, flatOptions.length, selectedDraft]);
|
|
20
|
+
const handleApply = useCallback(() => {
|
|
21
|
+
onApply();
|
|
22
|
+
toggleMenu();
|
|
23
|
+
}, [onApply, toggleMenu]);
|
|
24
|
+
const handleClear = useCallback(() => {
|
|
25
|
+
onClear();
|
|
26
|
+
toggleMenu();
|
|
27
|
+
}, [onClear, toggleMenu]);
|
|
28
|
+
const handleSelectedItems = useCallback((items) => {
|
|
29
|
+
setSelectedDraft?.(items);
|
|
30
|
+
}, [setSelectedDraft]);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const activeElement = document.activeElement;
|
|
33
|
+
return () => {
|
|
34
|
+
onClose();
|
|
35
|
+
if (activeElement) {
|
|
36
|
+
activeElement.focus();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
40
|
+
}, []);
|
|
41
|
+
const renderHeader = () => {
|
|
42
|
+
if (!showHeaderWithSelectAll && !header)
|
|
43
|
+
return undefined;
|
|
44
|
+
return (React.createElement(React.Fragment, null,
|
|
45
|
+
header,
|
|
46
|
+
showHeaderWithSelectAll && flatOptions.length > 0 && (React.createElement(Header$1, { ...headerProps }))));
|
|
47
|
+
};
|
|
48
|
+
return (React.createElement(OptionsList$1, { ...restProps, ref: ref, visibleOptions: visibleOptions, toggleMenu: toggleMenu, flatOptions: flatOptions, getOptionProps: getOptionProps, onApply: handleApply, onClear: handleClear, header: renderHeader(), selectedItems: selectedDraft, setSelectedItems: handleSelectedItems, footer: React.createElement(Footer$1, { handleApply: handleApply, handleClear: handleClear, showClear: showClear, selectedDraft: selectedDraft, dataTestId: restProps?.dataTestId }) }));
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const SELECT_ALL_KEY = 'select_all';
|
|
52
|
+
const selectAllOption = { key: SELECT_ALL_KEY, content: 'Выбрать все' };
|
|
53
|
+
function useSelectWithApply({ options, selected, onChange = () => null, OptionsList, optionsListProps = {}, showClear = true, showSelectAll = false, showHeaderWithSelectAll = false, showSearch = false, searchProps = {}, }) {
|
|
54
|
+
const [searchState, setSearchState] = useState('');
|
|
55
|
+
const [search, setSearch] = typeof searchProps?.value === 'string'
|
|
56
|
+
? [searchProps.value, searchProps.onChange]
|
|
57
|
+
: [searchState, setSearchState];
|
|
58
|
+
const accessor = searchProps.accessor || defaultAccessor;
|
|
59
|
+
const filterFn = searchProps.filterFn || defaultFilterFn;
|
|
60
|
+
const groupAccessor = searchProps.groupAccessor ?? defaultGroupAccessor;
|
|
61
|
+
const filterGroup = searchProps.filterGroup ?? false;
|
|
62
|
+
const { flatOptions, filteredOptions, selectedOptions } = useMemo(() => processOptions(options, selected, showSearch
|
|
63
|
+
? (option) => {
|
|
64
|
+
if (isGroup(option)) {
|
|
65
|
+
const groupAccessorValue = groupAccessor(option);
|
|
66
|
+
return (typeof groupAccessorValue === 'string' &&
|
|
67
|
+
filterFn(groupAccessorValue, search));
|
|
68
|
+
}
|
|
69
|
+
return filterFn(accessor(option), search);
|
|
70
|
+
}
|
|
71
|
+
: undefined, filterGroup), [options, selected, showSearch, filterGroup, filterFn, accessor, search, groupAccessor]);
|
|
72
|
+
const [selectedDraft, setSelectedDraft] = useState(selectedOptions);
|
|
73
|
+
const selectedOptionsRef = useRef(selectedOptions);
|
|
74
|
+
const handleApply = () => {
|
|
75
|
+
onChange({
|
|
76
|
+
selected: selectedDraft[0],
|
|
77
|
+
selectedMultiple: selectedDraft,
|
|
78
|
+
initiator: null,
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
const handleClear = () => {
|
|
82
|
+
setSelectedDraft([]);
|
|
83
|
+
onChange({
|
|
84
|
+
selected: null,
|
|
85
|
+
selectedMultiple: [],
|
|
86
|
+
initiator: null,
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
const handleToggleAll = () => {
|
|
90
|
+
setSelectedDraft(flatOptions.length === selectedDraft.length ? [] : flatOptions);
|
|
91
|
+
};
|
|
92
|
+
const handleChange = ({ initiator, ...restArgs }) => {
|
|
93
|
+
if (!initiator) {
|
|
94
|
+
onChange({
|
|
95
|
+
initiator: null,
|
|
96
|
+
...restArgs,
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const initiatorSelected = selectedDraft.includes(initiator) ||
|
|
101
|
+
(initiator.key === SELECT_ALL_KEY && selectedDraft.length === flatOptions.length);
|
|
102
|
+
if (initiator.key === SELECT_ALL_KEY) {
|
|
103
|
+
setSelectedDraft(initiatorSelected ? [] : flatOptions);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
setSelectedDraft(initiatorSelected
|
|
107
|
+
? selectedDraft.filter((o) => o !== initiator)
|
|
108
|
+
: selectedDraft.concat(initiator));
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const handleClose = () => setSelectedDraft(selectedOptionsRef.current);
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
// устанавливать selectedDraft если selectedOptions изменились
|
|
114
|
+
if (!deepEqual(selectedOptionsRef.current, selectedOptions)) {
|
|
115
|
+
setSelectedDraft(selectedOptions);
|
|
116
|
+
}
|
|
117
|
+
selectedOptionsRef.current = selectedOptions;
|
|
118
|
+
}, [selectedOptions]);
|
|
119
|
+
const memoizedOptions = useMemo(() => filteredOptions.length && showSelectAll
|
|
120
|
+
? [selectAllOption, ...filteredOptions]
|
|
121
|
+
: filteredOptions, [filteredOptions, showSelectAll]);
|
|
122
|
+
return {
|
|
123
|
+
OptionsList: OptionsListWithApply,
|
|
124
|
+
optionsListProps: {
|
|
125
|
+
...optionsListProps,
|
|
126
|
+
OptionsList,
|
|
127
|
+
showClear,
|
|
128
|
+
onClear: handleClear,
|
|
129
|
+
onApply: handleApply,
|
|
130
|
+
onClose: handleClose,
|
|
131
|
+
selectedDraft,
|
|
132
|
+
setSelectedDraft,
|
|
133
|
+
showHeaderWithSelectAll,
|
|
134
|
+
headerProps: {
|
|
135
|
+
indeterminate: !!selectedDraft.length && selectedDraft.length < flatOptions.length,
|
|
136
|
+
checked: selectedDraft.length === flatOptions.length,
|
|
137
|
+
onChange: handleToggleAll,
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
allowUnselect: true,
|
|
141
|
+
multiple: true,
|
|
142
|
+
options: memoizedOptions,
|
|
143
|
+
onChange: handleChange,
|
|
144
|
+
selected,
|
|
145
|
+
showSearch,
|
|
146
|
+
searchProps: showSearch
|
|
147
|
+
? {
|
|
148
|
+
...searchProps,
|
|
149
|
+
value: search,
|
|
150
|
+
onChange: setSearch,
|
|
151
|
+
}
|
|
152
|
+
: undefined,
|
|
153
|
+
/* Костыль для респонсив селекта. В мобильную версию хук уже зашит, и это единственный передать в мобилку оригинальные пропсы */
|
|
154
|
+
originalProps: {
|
|
155
|
+
options,
|
|
156
|
+
selected,
|
|
157
|
+
onChange,
|
|
158
|
+
OptionsList,
|
|
159
|
+
optionsListProps,
|
|
160
|
+
showClear,
|
|
161
|
+
showSelectAll,
|
|
162
|
+
showHeaderWithSelectAll,
|
|
163
|
+
showSearch,
|
|
164
|
+
searchProps,
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export { OptionsListWithApply as O, SELECT_ALL_KEY as S, useSelectWithApply as u };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SelectResponsive as Select } from './Component.responsive.js';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { BottomSheet } from '@alfalab/core-components-bottom-sheet/moderncssm';
|
|
3
|
+
import { FormControlMobile } from '@alfalab/core-components-form-control/moderncssm/mobile';
|
|
4
|
+
import { ModalMobile } from '@alfalab/core-components-modal/moderncssm/mobile';
|
|
5
|
+
import { Arrow } from '../components/arrow/Component.js';
|
|
6
|
+
import { BaseSelect } from '../components/base-select/Component.js';
|
|
7
|
+
import { Field } from '../components/field/Component.js';
|
|
8
|
+
import { Footer } from '../components/footer/Component.js';
|
|
9
|
+
import { Optgroup } from '../components/optgroup/Component.js';
|
|
10
|
+
import { Option } from '../components/option/Component.js';
|
|
11
|
+
import { OptionsList } from '../components/options-list/Component.js';
|
|
12
|
+
import { Search } from '../components/search/Component.js';
|
|
13
|
+
import { VirtualOptionsList } from '../components/virtual-options-list/Component.js';
|
|
14
|
+
import { u as useSelectWithApply } from '../hook-a8bc7fe8.js';
|
|
15
|
+
import { Header } from '../presets/useSelectWithApply/options-list-with-apply/header/Component.js';
|
|
16
|
+
|
|
17
|
+
const VIRTUAL_OPTIONS_LIST_THRESHOLD = 30;
|
|
18
|
+
const SelectMobile = forwardRef(({ autocomplete = false, multiple = false, allowUnselect = false, disabled = false, closeOnSelect = !multiple, circularNavigation = false, defaultOpen = false, open: openProp, size = 56, optionsSize = 56, fieldProps = {}, optionProps = {}, optionsListProps = {}, Arrow: Arrow$1 = Arrow, Field: Field$1 = Field, Optgroup: Optgroup$1 = Optgroup, Option: Option$1 = Option, Search: Search$1 = Search, selected, options, OptionsList: OptionsList$1 = options.length > VIRTUAL_OPTIONS_LIST_THRESHOLD
|
|
19
|
+
? VirtualOptionsList
|
|
20
|
+
: OptionsList, onChange, showClear = true, showSelectAll, showHeaderWithSelectAll, useWithApplyHook = multiple, showSearch, searchProps, ...restProps }, ref) => {
|
|
21
|
+
const applyProps = useSelectWithApply({
|
|
22
|
+
optionsListProps: {
|
|
23
|
+
...optionsListProps,
|
|
24
|
+
Footer,
|
|
25
|
+
},
|
|
26
|
+
OptionsList: OptionsList$1,
|
|
27
|
+
showSearch,
|
|
28
|
+
searchProps,
|
|
29
|
+
selected,
|
|
30
|
+
options,
|
|
31
|
+
onChange,
|
|
32
|
+
showClear,
|
|
33
|
+
showSelectAll,
|
|
34
|
+
});
|
|
35
|
+
const bottomAddons = useWithApplyHook && showHeaderWithSelectAll && (React.createElement(Header, { ...applyProps.optionsListProps.headerProps, mobile: true }));
|
|
36
|
+
return (React.createElement(BaseSelect, { ref: ref, view: 'mobile', autocomplete: autocomplete, multiple: multiple, allowUnselect: allowUnselect, disabled: disabled, closeOnSelect: closeOnSelect, circularNavigation: circularNavigation, defaultOpen: defaultOpen, open: openProp, size: size, optionsSize: optionsSize, fieldProps: {
|
|
37
|
+
FormControlComponent: FormControlMobile,
|
|
38
|
+
...fieldProps,
|
|
39
|
+
}, optionProps: optionProps, Arrow: Arrow$1, Field: Field$1, Optgroup: Optgroup$1, Option: Option$1, Search: Search$1, options: options, selected: selected, onChange: onChange, OptionsList: OptionsList$1, showSearch: showSearch, searchProps: searchProps, BottomSheet: BottomSheet, ModalMobile: ModalMobile, optionsListProps: optionsListProps, ...restProps, ...(restProps.isBottomSheet === false
|
|
40
|
+
? {
|
|
41
|
+
modalHeaderProps: {
|
|
42
|
+
bottomAddons,
|
|
43
|
+
...restProps.modalHeaderProps,
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
: {
|
|
47
|
+
bottomSheetProps: {
|
|
48
|
+
bottomAddons,
|
|
49
|
+
...restProps.bottomSheetProps,
|
|
50
|
+
},
|
|
51
|
+
}), ...(useWithApplyHook && applyProps) }));
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export { SelectMobile };
|