@ryuzaki13/react-foundation-ui 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advanced-search/index.d.ts +3 -0
- package/dist/advanced-search/index.d.ts.map +1 -0
- package/dist/advanced-search/index.js +361 -0
- package/dist/advanced-search/index.js.map +1 -0
- package/dist/advanced-search/lib/index.d.ts +2 -0
- package/dist/advanced-search/lib/index.d.ts.map +1 -0
- package/dist/advanced-search/lib/searchParts.d.ts +3 -0
- package/dist/advanced-search/lib/searchParts.d.ts.map +1 -0
- package/dist/advanced-search/model/index.d.ts +5 -0
- package/dist/advanced-search/model/index.d.ts.map +1 -0
- package/dist/advanced-search/model/types.d.ts +55 -0
- package/dist/advanced-search/model/types.d.ts.map +1 -0
- package/dist/advanced-search/model/useAdvancedSearch.d.ts +11 -0
- package/dist/advanced-search/model/useAdvancedSearch.d.ts.map +1 -0
- package/dist/advanced-search/model/useAdvancedSearchInitialSelected.d.ts +6 -0
- package/dist/advanced-search/model/useAdvancedSearchInitialSelected.d.ts.map +1 -0
- package/dist/advanced-search/model/useAdvancedSearchSelection.d.ts +13 -0
- package/dist/advanced-search/model/useAdvancedSearchSelection.d.ts.map +1 -0
- package/dist/advanced-search/ui/AdvancedSearchModal.d.ts +13 -0
- package/dist/advanced-search/ui/AdvancedSearchModal.d.ts.map +1 -0
- package/dist/advanced-search/ui/AdvancedSearchSelect.d.ts +8 -0
- package/dist/advanced-search/ui/AdvancedSearchSelect.d.ts.map +1 -0
- package/dist/advanced-search/ui/AdvancedSearchSelectUI.d.ts +9 -0
- package/dist/advanced-search/ui/AdvancedSearchSelectUI.d.ts.map +1 -0
- package/dist/advanced-search/ui/index.d.ts +2 -0
- package/dist/advanced-search/ui/index.d.ts.map +1 -0
- package/dist/badge/Badge.d.ts.map +1 -1
- package/dist/badge/index.js +1 -1
- package/dist/badge/stories/Badge.stories.js +22 -22
- package/dist/base-table/index.js +2 -2
- package/dist/base-table/lib/columnPinning.d.ts.map +1 -1
- package/dist/base-table/model/useTableColumnOrder.d.ts +1 -1
- package/dist/base-table/model/useTableColumnOrder.d.ts.map +1 -1
- package/dist/base-table/model/useTableColumnSizing.d.ts +1 -1
- package/dist/base-table/model/useTableColumnSizing.d.ts.map +1 -1
- package/dist/base-table/ui/BaseTable.d.ts +2 -2
- package/dist/base-table/ui/BaseTable.d.ts.map +1 -1
- package/dist/base-table/ui/BaseTableHeaderCell.d.ts.map +1 -1
- package/dist/base-table/ui/FormattedTableCell.d.ts.map +1 -1
- package/dist/button/index.js +7 -7
- package/dist/button/stories/Button.stories.js +1 -1
- package/dist/check-box/CheckBox.d.ts.map +1 -1
- package/dist/check-box/index.js +1 -1
- package/dist/check-box/stories/CheckBox.stories.js +25 -25
- package/dist/chunks/{BadgeList-DHW_Ktr3.js → BadgeList-DYgun2rf.js} +16 -16
- package/dist/chunks/BadgeList-DYgun2rf.js.map +1 -0
- package/dist/chunks/{Button-BZ_b-Kin.js → Button-CCWuggdA.js} +16 -16
- package/dist/chunks/{Button-BZ_b-Kin.js.map → Button-CCWuggdA.js.map} +1 -1
- package/dist/chunks/{CalendarView-B75faWIU.js → CalendarView-DjeTJkTT.js} +149 -149
- package/dist/chunks/{CalendarView-B75faWIU.js.map → CalendarView-DjeTJkTT.js.map} +1 -1
- package/dist/chunks/{CheckBox-Cck5w1Ud.js → CheckBox-BowNqqd3.js} +13 -13
- package/dist/chunks/CheckBox-BowNqqd3.js.map +1 -0
- package/dist/chunks/{DateInput-CINDYueM.js → DateInput--tfofQ2x.js} +68 -68
- package/dist/chunks/DateInput--tfofQ2x.js.map +1 -0
- package/dist/chunks/{DateRangePresetSelect-CyzGMvVp.js → DateRangePresetSelect-UgsfaOeM.js} +22 -22
- package/dist/chunks/{DateRangePresetSelect-CyzGMvVp.js.map → DateRangePresetSelect-UgsfaOeM.js.map} +1 -1
- package/dist/chunks/Detail-DHDMsg8q.js +80 -0
- package/dist/chunks/{Detail-DKolHye4.js.map → Detail-DHDMsg8q.js.map} +1 -1
- package/dist/chunks/{Dialog-BPS4BeWZ.js → Dialog-CFIvGxER.js} +8 -8
- package/dist/chunks/Dialog-CFIvGxER.js.map +1 -0
- package/dist/chunks/{DisclosureGroup-0BtaXO54.js → DisclosureGroup-CfRTkl6Z.js} +11 -11
- package/dist/chunks/DisclosureGroup-CfRTkl6Z.js.map +1 -0
- package/dist/chunks/{DropZone-hf7Em__0.js → DropZone-kJfbZU5g.js} +22 -22
- package/dist/chunks/DropZone-kJfbZU5g.js.map +1 -0
- package/dist/chunks/{DropdownMenu-Ds-trH4M.js → DropdownMenu-DQeR3y7M.js} +138 -138
- package/dist/chunks/DropdownMenu-DQeR3y7M.js.map +1 -0
- package/dist/chunks/{Flex-DbBdq336.js → Flex-DUYSL5TE.js} +16 -16
- package/dist/chunks/{Flex-DbBdq336.js.map → Flex-DUYSL5TE.js.map} +1 -1
- package/dist/chunks/Grid-ByIIytjh.js.map +1 -1
- package/dist/chunks/{Input-Ce2HXBUc.js → Input-BmjlpA09.js} +76 -76
- package/dist/chunks/Input-BmjlpA09.js.map +1 -0
- package/dist/chunks/{InputDateTime-DPtY_4Od.js → InputDateTime-CxfAFe2L.js} +56 -56
- package/dist/chunks/{InputDateTime-DPtY_4Od.js.map → InputDateTime-CxfAFe2L.js.map} +1 -1
- package/dist/chunks/{InputFile-ga5yJmdZ.js → InputFile-CyZu__B_.js} +17 -17
- package/dist/chunks/InputFile-CyZu__B_.js.map +1 -0
- package/dist/chunks/{InputFiles-Or2Nvfgk.js → InputFiles-CrTJV27R.js} +36 -36
- package/dist/chunks/InputFiles-CrTJV27R.js.map +1 -0
- package/dist/chunks/{InputImage-BeA5WJz1.js → InputImage-Cw8rPYQu.js} +18 -18
- package/dist/chunks/{InputImage-BeA5WJz1.js.map → InputImage-Cw8rPYQu.js.map} +1 -1
- package/dist/chunks/{LabeledExpandableActionPanel-Bx-DWmYz.js → LabeledExpandableActionPanel-D3kUvmFH.js} +25 -25
- package/dist/chunks/LabeledExpandableActionPanel-D3kUvmFH.js.map +1 -0
- package/dist/chunks/Listbox-BZlp5qHz.js +81 -0
- package/dist/chunks/Listbox-BZlp5qHz.js.map +1 -0
- package/dist/chunks/{MultiSelect-CBqTylqO.js → MultiSelect-D1XYuwH1.js} +113 -113
- package/dist/chunks/{MultiSelect-CBqTylqO.js.map → MultiSelect-D1XYuwH1.js.map} +1 -1
- package/dist/chunks/{NotificationsHost-BQc-zOr2.js → NotificationsHost-_icJx4xR.js} +34 -34
- package/dist/chunks/NotificationsHost-_icJx4xR.js.map +1 -0
- package/dist/chunks/{PresetRangeDateInput-YBQm_4Fb.js → PresetRangeDateInput-CapirptQ.js} +11 -11
- package/dist/chunks/{PresetRangeDateInput-YBQm_4Fb.js.map → PresetRangeDateInput-CapirptQ.js.map} +1 -1
- package/dist/chunks/{RadioButton-DJp31HFR.js → RadioButton-D0uA0rX_.js} +13 -13
- package/dist/chunks/RadioButton-D0uA0rX_.js.map +1 -0
- package/dist/chunks/RadioGroup-B9XjkcOy.js +121 -0
- package/dist/chunks/{RadioGroup-BAhN1d1X.js.map → RadioGroup-B9XjkcOy.js.map} +1 -1
- package/dist/chunks/{Select-B7k_8_Lf.js → Select-CXeVjVKA.js} +11 -11
- package/dist/chunks/Select-CXeVjVKA.js.map +1 -0
- package/dist/chunks/{SerializableSelect-53uNCqdE.js → SerializableSelect-DkYeJtAO.js} +2 -2
- package/dist/chunks/{SerializableSelect-53uNCqdE.js.map → SerializableSelect-DkYeJtAO.js.map} +1 -1
- package/dist/chunks/{SingleDateTimeInput-CwvIbwje.js → SingleDateTimeInput-BmeuVGQT.js} +86 -86
- package/dist/chunks/SingleDateTimeInput-BmeuVGQT.js.map +1 -0
- package/dist/chunks/{Splitter-NjNFuEq4.js → Splitter-BFkVGVRb.js} +32 -32
- package/dist/chunks/{Splitter-NjNFuEq4.js.map → Splitter-BFkVGVRb.js.map} +1 -1
- package/dist/chunks/StateSelect-1jH3uLz9.js +78 -0
- package/dist/chunks/{StateSelect-D0wuUdT9.js.map → StateSelect-1jH3uLz9.js.map} +1 -1
- package/dist/chunks/{Switch-B476FBUD.js → Switch-B57Qmy1z.js} +19 -19
- package/dist/chunks/Switch-B57Qmy1z.js.map +1 -0
- package/dist/chunks/{TextEditorLexicalClient-DcixYuo4.js → TextEditorLexicalClient-DRhAswpP.js} +204 -204
- package/dist/chunks/{TextEditorLexicalClient-DcixYuo4.js.map → TextEditorLexicalClient-DRhAswpP.js.map} +1 -1
- package/dist/chunks/{Textarea-DeJJjjkI.js → Textarea-C9UdUueF.js} +2 -2
- package/dist/chunks/{Textarea-DeJJjjkI.js.map → Textarea-C9UdUueF.js.map} +1 -1
- package/dist/chunks/{TimePanel-_kF2RtHk.js → TimePanel-b4saqoUY.js} +27 -27
- package/dist/chunks/TimePanel-b4saqoUY.js.map +1 -0
- package/dist/chunks/{Toggle-C_fE-bkM.js → Toggle-DVqOQXmt.js} +18 -18
- package/dist/chunks/{Toggle-C_fE-bkM.js.map → Toggle-DVqOQXmt.js.map} +1 -1
- package/dist/chunks/{TreeMultiSelect-DRYNx7u5.js → TreeMultiSelect-CfQhlfnC.js} +6 -6
- package/dist/chunks/{TreeMultiSelect-DRYNx7u5.js.map → TreeMultiSelect-CfQhlfnC.js.map} +1 -1
- package/dist/chunks/{TreePickerBase-DYzTsSBQ.js → TreePickerBase-BBUOWsSu.js} +154 -154
- package/dist/chunks/TreePickerBase-BBUOWsSu.js.map +1 -0
- package/dist/chunks/{TreeSelect-DGLDu6qc.js → TreeSelect-2wUXs90E.js} +6 -6
- package/dist/chunks/{TreeSelect-DGLDu6qc.js.map → TreeSelect-2wUXs90E.js.map} +1 -1
- package/dist/chunks/base-table-CoQlKABk.js +514 -0
- package/dist/chunks/base-table-CoQlKABk.js.map +1 -0
- package/dist/chunks/{floating-arrow-CdRV69sg.js → floating-arrow-BE-z4QkE.js} +7 -7
- package/dist/chunks/{floating-arrow-CdRV69sg.js.map → floating-arrow-BE-z4QkE.js.map} +1 -1
- package/dist/chunks/input-search-Dw4rnJBq.js +30 -0
- package/dist/chunks/input-search-Dw4rnJBq.js.map +1 -0
- package/dist/chunks/{layout-picker-BA9vA8JI.js → layout-picker-MWaImn3L.js} +34 -34
- package/dist/chunks/layout-picker-MWaImn3L.js.map +1 -0
- package/dist/chunks/{misc-DrmMj8GO.js → misc-DoqZBMof.js} +100 -100
- package/dist/chunks/misc-DoqZBMof.js.map +1 -0
- package/dist/chunks/{modal-DqVcZws_.js → modal-B3HY3laL.js} +40 -40
- package/dist/chunks/modal-B3HY3laL.js.map +1 -0
- package/dist/chunks/multi-select-BzYIviCU.js +1305 -0
- package/dist/chunks/multi-select-BzYIviCU.js.map +1 -0
- package/dist/chunks/{picker-Cj4RnJh6.js → picker-Dg55Ss-B.js} +73 -73
- package/dist/chunks/picker-Dg55Ss-B.js.map +1 -0
- package/dist/chunks/{popover-C79P5bm2.js → popover-xJJqy1v6.js} +52 -52
- package/dist/chunks/popover-xJJqy1v6.js.map +1 -0
- package/dist/chunks/{separator-CIqnk2z9.js → separator-B72Aq-6a.js} +2 -2
- package/dist/chunks/{separator-CIqnk2z9.js.map → separator-B72Aq-6a.js.map} +1 -1
- package/dist/chunks/{slider-34wxzKkG.js → slider-CFKsfxFp.js} +83 -83
- package/dist/chunks/slider-CFKsfxFp.js.map +1 -0
- package/dist/chunks/sortable-DcTIAbjD.js +185 -0
- package/dist/chunks/sortable-DcTIAbjD.js.map +1 -0
- package/dist/chunks/{table-BYA0hCj7.js → table-Dc3AqMzP.js} +21 -21
- package/dist/chunks/table-Dc3AqMzP.js.map +1 -0
- package/dist/chunks/{table-column-interactions-DPyJDD7P.js → table-column-interactions-6RGjmiI5.js} +24 -24
- package/dist/chunks/{table-column-interactions-DPyJDD7P.js.map → table-column-interactions-6RGjmiI5.js.map} +1 -1
- package/dist/chunks/{tabs-CjU2KCgs.js → tabs-DlnVVMJl.js} +96 -96
- package/dist/chunks/{tabs-CjU2KCgs.js.map → tabs-DlnVVMJl.js.map} +1 -1
- package/dist/chunks/{toolbar-C-Ziw_Uh.js → toolbar-BCZNdRXM.js} +2 -2
- package/dist/chunks/{toolbar-C-Ziw_Uh.js.map → toolbar-BCZNdRXM.js.map} +1 -1
- package/dist/chunks/{wheel-picker-DUHGy7wE.js → wheel-picker-FS58cRsQ.js} +23 -23
- package/dist/chunks/{wheel-picker-DUHGy7wE.js.map → wheel-picker-FS58cRsQ.js.map} +1 -1
- package/dist/context-menu/components/MenuContent.d.ts.map +1 -1
- package/dist/context-menu/components/MenuContext.d.ts.map +1 -1
- package/dist/context-menu/components/MenuRoot.d.ts.map +1 -1
- package/dist/context-menu/components/RadialMenuContent.d.ts.map +1 -1
- package/dist/context-menu/index.js +1 -1
- package/dist/context-menu/stories/ContextMenu.stories.js +45 -45
- package/dist/date-input/index.js +2 -2
- package/dist/date-input/lib/types.d.ts.map +1 -1
- package/dist/date-input/stories/DateInput.stories.js +2 -2
- package/dist/date-input/ui/CalendarView.d.ts.map +1 -1
- package/dist/date-input/ui/DateInput.d.ts.map +1 -1
- package/dist/date-range-preset-select/index.js +1 -1
- package/dist/date-range-preset-select/stories/DateRangePresetSelect.stories.js +8 -8
- package/dist/date-time-input/index.js +1 -1
- package/dist/date-time-input/lib/dateTimeValue.d.ts.map +1 -1
- package/dist/date-time-input/stories/SingleDateTimeInput.stories.js +38 -38
- package/dist/date-time-input/stories/TimePanel.stories.js +9 -9
- package/dist/date-time-input/ui/SingleDateTimeInput.d.ts.map +1 -1
- package/dist/detail/index.js +1 -1
- package/dist/detail/stories/Detail.stories.js +1 -1
- package/dist/dialog/Dialog.d.ts.map +1 -1
- package/dist/dialog/index.js +1 -1
- package/dist/dialog/stories/Dialog.stories.js +16 -16
- package/dist/disclosure/Disclosure.d.ts.map +1 -1
- package/dist/disclosure/index.js +1 -1
- package/dist/disclosure/stories/Disclosure.stories.js +1 -1
- package/dist/drop-zone/DropZone.d.ts.map +1 -1
- package/dist/drop-zone/index.js +1 -1
- package/dist/drop-zone/stories/DropZone.stories.d.ts.map +1 -1
- package/dist/drop-zone/stories/DropZone.stories.js +14 -14
- package/dist/drop-zone/stories/DropZone.stories.js.map +1 -1
- package/dist/errors/ErrorDisplay.d.ts.map +1 -1
- package/dist/errors/index.js +47 -47
- package/dist/errors/index.js.map +1 -1
- package/dist/expandable-action-panel/ExpandableActionPanel.d.ts.map +1 -1
- package/dist/expandable-action-panel/index.js +1 -1
- package/dist/expandable-action-panel/stories/ExpandableActionPanel.stories.js +28 -28
- package/dist/flex/index.js +2 -2
- package/dist/flex/stories/Flex.stories.js +2 -2
- package/dist/floating-arrow/index.js +1 -1
- package/dist/fullscreen-portal/index.js +6 -6
- package/dist/grid/stories/Grid.stories.js +1 -1
- package/dist/image/index.js +123 -123
- package/dist/image/index.js.map +1 -1
- package/dist/image/ui/ImageSelection.d.ts.map +1 -1
- package/dist/input/Input.d.ts.map +1 -1
- package/dist/input/index.js +1 -1
- package/dist/input/stories/Input.stories.js +11 -11
- package/dist/input-date-time/index.js +1 -1
- package/dist/input-date-time/stories/InputDateTime.stories.js +11 -11
- package/dist/input-file/InputFile.d.ts.map +1 -1
- package/dist/input-file/index.js +1 -1
- package/dist/input-file/stories/InputFile.stories.d.ts.map +1 -1
- package/dist/input-file/stories/InputFile.stories.js +9 -9
- package/dist/input-file/stories/InputFile.stories.js.map +1 -1
- package/dist/input-files/InputFilesList.d.ts.map +1 -1
- package/dist/input-files/index.js +1 -1
- package/dist/input-files/stories/InputFiles.stories.d.ts +1 -1
- package/dist/input-files/stories/InputFiles.stories.d.ts.map +1 -1
- package/dist/input-files/stories/InputFiles.stories.js +9 -9
- package/dist/input-files/stories/InputFiles.stories.js.map +1 -1
- package/dist/input-image/index.js +1 -1
- package/dist/input-image/stories/InputImage.stories.d.ts.map +1 -1
- package/dist/input-image/stories/InputImage.stories.js +15 -15
- package/dist/input-image/stories/InputImage.stories.js.map +1 -1
- package/dist/input-search/index.js +2 -30
- package/dist/layout-picker/index.js +1 -1
- package/dist/layout-picker/stories/LayoutPicker.stories.js +52 -52
- package/dist/layout-picker/ui/LayoutPicker.d.ts.map +1 -1
- package/dist/list/List.d.ts.map +1 -1
- package/dist/list/index.js +30 -30
- package/dist/list/index.js.map +1 -1
- package/dist/listbox/Listbox.d.ts.map +1 -1
- package/dist/listbox/index.js +1 -1
- package/dist/listbox/stories/Listbox.stories.js +19 -19
- package/dist/misc/CopyTextWrapper.d.ts.map +1 -1
- package/dist/misc/OneStepScroller.d.ts.map +1 -1
- package/dist/misc/StateIcon.d.ts.map +1 -1
- package/dist/misc/index.js +1 -1
- package/dist/modal/Modal.d.ts +5 -1
- package/dist/modal/Modal.d.ts.map +1 -1
- package/dist/modal/index.js +1 -1
- package/dist/modal/stories/Modal.stories.js +55 -55
- package/dist/multi-select/index.js +3 -35
- package/dist/multi-select/model/useODataMultiSelect.d.ts +23 -0
- package/dist/multi-select/model/useODataMultiSelect.d.ts.map +1 -0
- package/dist/multi-select/ui/MultiSelect.d.ts +1 -1
- package/dist/multi-select/ui/MultiSelect.d.ts.map +1 -1
- package/dist/multi-select/ui/ODataDependentMultiSelect.d.ts +20 -0
- package/dist/multi-select/ui/ODataDependentMultiSelect.d.ts.map +1 -0
- package/dist/multi-select/ui/ODataDependentSegmentMultiSelect.d.ts +21 -0
- package/dist/multi-select/ui/ODataDependentSegmentMultiSelect.d.ts.map +1 -0
- package/dist/multi-select/ui/ODataMultiSelect.d.ts +7 -0
- package/dist/multi-select/ui/ODataMultiSelect.d.ts.map +1 -0
- package/dist/multi-select/ui/SerializableMultiSelect.d.ts.map +1 -1
- package/dist/multi-select/ui/index.d.ts +3 -0
- package/dist/multi-select/ui/index.d.ts.map +1 -1
- package/dist/multi-select/ui/stories/MultiSelect.stories.js +17 -17
- package/dist/multi-select/ui/stories/ODataMultiSelect.stories.d.ts +44 -0
- package/dist/multi-select/ui/stories/ODataMultiSelect.stories.d.ts.map +1 -0
- package/dist/notifications/index.js +1 -1
- package/dist/notifications/model/NotificationsProvider.d.ts.map +1 -1
- package/dist/notifications/ui/NotificationsHost.d.ts.map +1 -1
- package/dist/notifications/ui/stories/NotificationsHost.stories.js +59 -59
- package/dist/period-select/PeriodSelect.d.ts +1 -1
- package/dist/period-select/PeriodSelect.d.ts.map +1 -1
- package/dist/period-select/index.js +20 -20
- package/dist/period-select/index.js.map +1 -1
- package/dist/period-select/lib/periodSelect.d.ts.map +1 -1
- package/dist/period-select/stories/PeriodSelect.stories.d.ts.map +1 -1
- package/dist/period-select/stories/PeriodSelect.stories.js +17 -17
- package/dist/period-select/stories/PeriodSelect.stories.js.map +1 -1
- package/dist/picker/PickerPopup.d.ts.map +1 -1
- package/dist/picker/PickerTriggerActions.d.ts.map +1 -1
- package/dist/picker/index.js +1 -1
- package/dist/picker/model/usePickerFloatingListbox.d.ts.map +1 -1
- package/dist/popover/FloatingPopover.d.ts.map +1 -1
- package/dist/popover/components/PopoverContent.d.ts.map +1 -1
- package/dist/popover/components/PopoverContext.d.ts.map +1 -1
- package/dist/popover/index.js +1 -1
- package/dist/popover/stories/Popover.stories.js +16 -16
- package/dist/preset-range-date-input/index.js +1 -1
- package/dist/preset-range-date-input/ui/stories/PresetRangeDateInput.stories.js +9 -9
- package/dist/preset-select/index.js +1 -1
- package/dist/radio-button/RadioButton.d.ts.map +1 -1
- package/dist/radio-button/index.js +1 -1
- package/dist/radio-button/stories/RadioButton.stories.js +11 -11
- package/dist/radio-group/index.js +1 -1
- package/dist/radio-group/stories/RadioGroup.stories.js +21 -21
- package/dist/select/ODataSelect.d.ts +9 -0
- package/dist/select/ODataSelect.d.ts.map +1 -0
- package/dist/select/Select.d.ts.map +1 -1
- package/dist/select/index.js +2 -2
- package/dist/select/model/useODataSelect.d.ts +25 -0
- package/dist/select/model/useODataSelect.d.ts.map +1 -0
- package/dist/select/model/useODataSelectBase.d.ts +24 -0
- package/dist/select/model/useODataSelectBase.d.ts.map +1 -0
- package/dist/select/stories/ODataSelect.stories.d.ts +46 -0
- package/dist/select/stories/ODataSelect.stories.d.ts.map +1 -0
- package/dist/select/stories/Select.stories.js +23 -23
- package/dist/select/stories/SerializableSelect.stories.js +22 -22
- package/dist/select/stories/odataStoryFixtures.d.ts +35 -0
- package/dist/select/stories/odataStoryFixtures.d.ts.map +1 -0
- package/dist/separator/index.js +1 -1
- package/dist/simple-table/index.js +5 -5
- package/dist/simple-table/index.js.map +1 -1
- package/dist/slider/Slider.d.ts.map +1 -1
- package/dist/slider/index.js +1 -1
- package/dist/slider/stories/Slider.stories.js +32 -32
- package/dist/slider/stories/SliderInput.stories.js +39 -39
- package/dist/sortable/Sortable.d.ts.map +1 -1
- package/dist/sortable/SortableDragHandle.d.ts.map +1 -1
- package/dist/sortable/index.js +1 -1
- package/dist/sortable/stories/Sortable.stories.js +23 -23
- package/dist/splitter/index.js +1 -1
- package/dist/splitter/stories/Splitter.stories.js +1 -1
- package/dist/state-select/index.js +1 -1
- package/dist/state-select/stories/StateSelect.stories.d.ts.map +1 -1
- package/dist/state-select/stories/StateSelect.stories.js +23 -23
- package/dist/state-select/stories/StateSelect.stories.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/switch/Switch.d.ts.map +1 -1
- package/dist/switch/index.js +1 -1
- package/dist/switch/stories/Switch.stories.js +11 -11
- package/dist/table/Table.d.ts +1 -1
- package/dist/table/Table.d.ts.map +1 -1
- package/dist/table/index.js +1 -1
- package/dist/table/stories/Table.stories.d.ts +155 -0
- package/dist/table/stories/Table.stories.d.ts.map +1 -0
- package/dist/table-column-interactions/TableHeaderInteractionCell.d.ts.map +1 -1
- package/dist/table-column-interactions/index.js +1 -1
- package/dist/table-sorting/index.js +1 -1
- package/dist/tabs/index.js +1 -1
- package/dist/tabs/stories/Tabs.stories.d.ts.map +1 -1
- package/dist/tabs/stories/Tabs.stories.js +39 -39
- package/dist/tabs/stories/Tabs.stories.js.map +1 -1
- package/dist/text/TextOverflow.d.ts.map +1 -1
- package/dist/text/index.js +20 -20
- package/dist/text/index.js.map +1 -1
- package/dist/text-editor/TextEditorLexicalClient.d.ts.map +1 -1
- package/dist/text-editor/index.js +3 -3
- package/dist/text-editor/toolbar/index.js +1 -1
- package/dist/textarea/index.js +1 -1
- package/dist/textarea/stories/Textarea.stories.js +8 -8
- package/dist/three-scene/index.js +7 -7
- package/dist/toggle/index.js +1 -1
- package/dist/toggle/stories/Toggle.stories.js +7 -7
- package/dist/toolbar/index.js +16 -16
- package/dist/tree/index.js +24 -24
- package/dist/tree-select/ODataTreeMultiSelect.d.ts +12 -0
- package/dist/tree-select/ODataTreeMultiSelect.d.ts.map +1 -0
- package/dist/tree-select/ODataTreeSelect.d.ts +13 -0
- package/dist/tree-select/ODataTreeSelect.d.ts.map +1 -0
- package/dist/tree-select/TreeNodeContent.d.ts.map +1 -1
- package/dist/tree-select/TreePickerBase.d.ts.map +1 -1
- package/dist/tree-select/index.js +2 -2
- package/dist/tree-select/model/buildODataTreeNodes.d.ts +12 -0
- package/dist/tree-select/model/buildODataTreeNodes.d.ts.map +1 -0
- package/dist/tree-select/model/resolveOrderedTreeSegmentItems.d.ts +4 -0
- package/dist/tree-select/model/resolveOrderedTreeSegmentItems.d.ts.map +1 -0
- package/dist/tree-select/model/useODataTreeData.d.ts +11 -0
- package/dist/tree-select/model/useODataTreeData.d.ts.map +1 -0
- package/dist/tree-select/stories/ODataTreeMultiSelect.stories.d.ts +55 -0
- package/dist/tree-select/stories/ODataTreeMultiSelect.stories.d.ts.map +1 -0
- package/dist/tree-select/stories/ODataTreeSelect.stories.d.ts +54 -0
- package/dist/tree-select/stories/ODataTreeSelect.stories.d.ts.map +1 -0
- package/dist/tree-select/stories/TreeMultiSelect.stories.js +9 -9
- package/dist/tree-select/stories/TreeSelect.stories.js +9 -9
- package/dist/tree-table/TreeTable.d.ts +1 -1
- package/dist/tree-table/TreeTable.d.ts.map +1 -1
- package/dist/tree-table/index.js +32 -32
- package/dist/tree-table/index.js.map +1 -1
- package/dist/tree-table/stories/TreeTable.stories.d.ts +158 -0
- package/dist/tree-table/stories/TreeTable.stories.d.ts.map +1 -0
- package/dist/wheel-picker/index.js +1 -1
- package/package.json +15 -4
- package/dist/chunks/BadgeList-DHW_Ktr3.js.map +0 -1
- package/dist/chunks/CheckBox-Cck5w1Ud.js.map +0 -1
- package/dist/chunks/DateInput-CINDYueM.js.map +0 -1
- package/dist/chunks/Detail-DKolHye4.js +0 -80
- package/dist/chunks/Dialog-BPS4BeWZ.js.map +0 -1
- package/dist/chunks/DisclosureGroup-0BtaXO54.js.map +0 -1
- package/dist/chunks/DropZone-hf7Em__0.js.map +0 -1
- package/dist/chunks/DropdownMenu-Ds-trH4M.js.map +0 -1
- package/dist/chunks/Input-Ce2HXBUc.js.map +0 -1
- package/dist/chunks/InputFile-ga5yJmdZ.js.map +0 -1
- package/dist/chunks/InputFiles-Or2Nvfgk.js.map +0 -1
- package/dist/chunks/LabeledExpandableActionPanel-Bx-DWmYz.js.map +0 -1
- package/dist/chunks/Listbox-CY1wQOCP.js +0 -81
- package/dist/chunks/Listbox-CY1wQOCP.js.map +0 -1
- package/dist/chunks/NotificationsHost-BQc-zOr2.js.map +0 -1
- package/dist/chunks/RadioButton-DJp31HFR.js.map +0 -1
- package/dist/chunks/RadioGroup-BAhN1d1X.js +0 -121
- package/dist/chunks/Select-B7k_8_Lf.js.map +0 -1
- package/dist/chunks/SingleDateTimeInput-CwvIbwje.js.map +0 -1
- package/dist/chunks/StateSelect-D0wuUdT9.js +0 -78
- package/dist/chunks/Switch-B476FBUD.js.map +0 -1
- package/dist/chunks/TimePanel-_kF2RtHk.js.map +0 -1
- package/dist/chunks/TreePickerBase-DYzTsSBQ.js.map +0 -1
- package/dist/chunks/base-table-DVje02Zi.js +0 -514
- package/dist/chunks/base-table-DVje02Zi.js.map +0 -1
- package/dist/chunks/layout-picker-BA9vA8JI.js.map +0 -1
- package/dist/chunks/misc-DrmMj8GO.js.map +0 -1
- package/dist/chunks/modal-DqVcZws_.js.map +0 -1
- package/dist/chunks/picker-Cj4RnJh6.js.map +0 -1
- package/dist/chunks/popover-C79P5bm2.js.map +0 -1
- package/dist/chunks/slider-34wxzKkG.js.map +0 -1
- package/dist/chunks/sortable-CwDHC3CA.js +0 -185
- package/dist/chunks/sortable-CwDHC3CA.js.map +0 -1
- package/dist/chunks/table-BYA0hCj7.js.map +0 -1
- package/dist/input-search/index.js.map +0 -1
- package/dist/multi-select/index.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputDateTime-DPtY_4Od.js","names":[],"sources":["../../src/input-date-time/InputDateTime.module.scss","../../src/input-date-time/maskParser.ts","../../src/input-date-time/useMaskedSegments.ts","../../src/input-date-time/InputDateTime.tsx"],"sourcesContent":["@use \"@/styles/mixins\" as *;\n\n.segmentInput {\n\tborder: none;\n\tbackground: transparent;\n\toutline: none;\n\tpadding: 0;\n\tmargin: 0;\n\tfont-family: var(--font-family-mono);\n\tcolor: inherit;\n\ttext-align: center;\n\tcaret-color: var(--content-0);\n\tfont-variant-numeric: tabular-nums;\n\n\t&::placeholder {\n\t\tcolor: var(--content-2);\n\t\t// font-size: var(--font-size-sm);\n\t}\n\n\t&::selection {\n\t\tbackground-color: var(--focus-ring);\n\t\tcolor: var(--surface-0);\n\t}\n\n\t// Remove spin buttons\n\t&::-webkit-inner-spin-button,\n\t&::-webkit-outer-spin-button {\n\t\t-webkit-appearance: none;\n\t\tmargin: 0;\n\t}\n\n\t&:disabled {\n\t\topacity: 0.25;\n\t}\n}\n\n.separator {\n\tuser-select: none;\n\tcolor: var(--content-2);\n\tflex-shrink: 0;\n\n\t&[data-disabled] {\n\t\topacity: 0.25;\n\t}\n}\n","import {\n\ttype DateMaskSegment,\n\ttype DateSegmentId,\n\tdateToIndexedSegmentValues,\n\ttype EditableDateSegment,\n\tindexedSegmentsToDate,\n\ttype LiteralDateSegment,\n\tparseDateSegmentMask\n} from \"@ryuzaki13/react-foundation-lib/date-segments\";\n\n/**\n * Совместимый тип сегмента для существующего `InputDateTime`.\n */\nexport type SegmentType = DateSegmentId;\n\n/**\n * Совместимый редактируемый сегмент для существующего `InputDateTime`.\n */\nexport interface EditableSegment extends Omit<EditableDateSegment, \"id\"> {\n\ttype: SegmentType;\n}\n\n/**\n * Совместимый литеральный сегмент для существующего `InputDateTime`.\n */\nexport type LiteralSegment = LiteralDateSegment;\n\n/**\n * Совместимый тип сегмента маски для существующего `InputDateTime`.\n */\nexport type Segment = EditableSegment | LiteralSegment;\n\n/**\n * Разбирает строковую маску, сохраняя прежний контракт `InputDateTime`.\n */\nexport function parseMask(mask: string): Segment[] {\n\treturn parseDateSegmentMask(mask).map((segment) => (segment.kind === \"editable\" ? { ...segment, type: segment.id } : segment));\n}\n\n/**\n * Преобразует Date в карту значений сегментов по их совместимым типам.\n */\nexport function dateToSegmentValues(date: Date | undefined, segments: Segment[]): Map<SegmentType, string> {\n\tconst indexedValues = dateToIndexedSegmentValues(date, segments as DateMaskSegment[]);\n\tconst values = new Map<SegmentType, string>();\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind !== \"editable\") return;\n\t\tvalues.set(segment.type, indexedValues.get(index) ?? \"\");\n\t});\n\n\treturn values;\n}\n\n/**\n * Собирает строгий Date из карты сегментов старого формата.\n */\nexport function segmentsToDate(segments: Segment[], values: Map<SegmentType, string>): Date | null {\n\tconst indexedValues = new Map<number, string>();\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind !== \"editable\") return;\n\t\tindexedValues.set(index, values.get(segment.type) ?? \"\");\n\t});\n\n\treturn indexedSegmentsToDate(segments as DateMaskSegment[], indexedValues);\n}\n","import React, { useCallback, useMemo, useRef, useState } from \"react\";\n\nimport { dateToSegmentValues, EditableSegment, parseMask, segmentsToDate, SegmentType } from \"./maskParser\";\n\ninterface UseMaskedSegmentsOptions {\n\tmask: string;\n\tvalue: Date | undefined;\n\tonChange: (date: Date) => void;\n\tonClearError?: () => void;\n\tdisabled?: boolean;\n}\n\n// Вычисляет Map<index, string> из Date и массива сегментов\nfunction buildSegmentMap(date: Date | undefined, segments: ReturnType<typeof parseMask>): Map<number, string> {\n\tconst typeValues = dateToSegmentValues(date, segments);\n\tconst map = new Map<number, string>();\n\n\tsegments.forEach((seg, i) => {\n\t\tif (seg.kind === \"editable\") {\n\t\t\tmap.set(i, typeValues.get(seg.type) ?? \"\");\n\t\t}\n\t});\n\n\treturn map;\n}\n\n// TODO: Duplicate date-time-input/model/useDateTimeSegments\nfunction resolveEditableIndices(segments: ReturnType<typeof parseMask>): number[] {\n\tconst indices: number[] = [];\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind === \"editable\") {\n\t\t\tindices.push(index);\n\t\t}\n\t});\n\n\treturn indices;\n}\n\nexport function useMaskedSegments({ mask, value, onChange, onClearError, disabled }: UseMaskedSegmentsOptions) {\n\tconst segments = useMemo(() => parseMask(mask), [mask]);\n\n\tconst editableIndices = useMemo(() => resolveEditableIndices(segments), [segments]);\n\n\t// Значения сегментов, вычисленные из пропса value (источник истины)\n\tconst committedValues = useMemo(() => buildSegmentMap(value, segments), [value, segments]);\n\n\t// Локальные «грязные» значения при редактировании (null → используем committedValues)\n\tconst [dirtyValues, setDirtyValues] = useState<Map<number, string> | null>(null);\n\n\t// Сброс грязного состояния при внешнем изменении value (паттерн «adjusting state during render»)\n\tconst [prevValueTime, setPrevValueTime] = useState(() => value?.getTime());\n\tconst currentValueTime = value?.getTime();\n\tif (currentValueTime !== prevValueTime) {\n\t\tsetPrevValueTime(currentValueTime);\n\t\tsetDirtyValues(null);\n\t}\n\n\t// Текущие отображаемые значения\n\tconst segmentValues = dirtyValues ?? committedValues;\n\n\tconst refsMap = useRef<Map<number, HTMLInputElement>>(new Map());\n\tconst blurTimeout = useRef<number>(0);\n\tconst [isFocused, setIsFocused] = useState(false);\n\n\tconst tryFireOnChange = useCallback(\n\t\t(updatedValues: Map<number, string>) => {\n\t\t\tconst typeValues = new Map<SegmentType, string>();\n\n\t\t\tsegments.forEach((seg, i) => {\n\t\t\t\tif (seg.kind === \"editable\") {\n\t\t\t\t\ttypeValues.set(seg.type, updatedValues.get(i) ?? \"\");\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst date = segmentsToDate(segments, typeValues);\n\t\t\tif (date !== null) {\n\t\t\t\tonChange(date);\n\t\t\t}\n\t\t},\n\t\t[segments, onChange]\n\t);\n\n\tconst focusSegment = useCallback((index: number, selectAll = true) => {\n\t\tconst el = refsMap.current.get(index);\n\t\tif (el) {\n\t\t\tel.focus();\n\t\t\tif (selectAll) {\n\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t}\n\t\t}\n\t}, []);\n\n\tconst getNextEditable = useCallback(\n\t\t(currentIndex: number): number | null => {\n\t\t\tconst pos = editableIndices.indexOf(currentIndex);\n\t\t\treturn pos < editableIndices.length - 1 ? editableIndices[pos + 1] : null;\n\t\t},\n\t\t[editableIndices]\n\t);\n\n\tconst getPrevEditable = useCallback(\n\t\t(currentIndex: number): number | null => {\n\t\t\tconst pos = editableIndices.indexOf(currentIndex);\n\t\t\treturn pos > 0 ? editableIndices[pos - 1] : null;\n\t\t},\n\t\t[editableIndices]\n\t);\n\n\tconst padValue = useCallback((val: string, segment: EditableSegment): string => {\n\t\treturn val.padStart(segment.length, \"0\");\n\t}, []);\n\n\tconst registerRef = useCallback(\n\t\t(index: number) => (el: HTMLInputElement | null) => {\n\t\t\tif (el) {\n\t\t\t\trefsMap.current.set(index, el);\n\t\t\t} else {\n\t\t\t\trefsMap.current.delete(index);\n\t\t\t}\n\t\t},\n\t\t[]\n\t);\n\n\tconst handleInput = useCallback(\n\t\t(index: number) => (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tif (disabled) return;\n\n\t\t\tconst segment = segments[index] as EditableSegment;\n\t\t\tconst raw = e.target.value.replace(/\\D/g, \"\");\n\t\t\tconst clamped = raw.slice(0, segment.length);\n\n\t\t\tconst updated = new Map(segmentValues);\n\t\t\tupdated.set(index, clamped);\n\t\t\tsetDirtyValues(updated);\n\n\t\t\tonClearError?.();\n\n\t\t\t// Авто-переход к следующему сегменту при заполнении текущего\n\t\t\tif (clamped.length === segment.length) {\n\t\t\t\tconst next = getNextEditable(index);\n\t\t\t\tif (next !== null) {\n\t\t\t\t\trequestAnimationFrame(() => focusSegment(next));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttryFireOnChange(updated);\n\t\t},\n\t\t[disabled, segments, segmentValues, onClearError, getNextEditable, focusSegment, tryFireOnChange]\n\t);\n\n\tconst handleKeyDown = useCallback(\n\t\t(index: number) => (e: React.KeyboardEvent<HTMLInputElement>) => {\n\t\t\tif (disabled) return;\n\n\t\t\tconst segment = segments[index] as EditableSegment;\n\t\t\tconst currentVal = segmentValues.get(index) ?? \"\";\n\t\t\tconst el = e.currentTarget;\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase \"ArrowRight\": {\n\t\t\t\t\tif (el.selectionStart === currentVal.length || currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst next = getNextEditable(index);\n\t\t\t\t\t\tif (next !== null) focusSegment(next);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowLeft\": {\n\t\t\t\t\tif (el.selectionStart === 0 || currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst prev = getPrevEditable(index);\n\t\t\t\t\t\tif (prev !== null) focusSegment(prev);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowUp\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tlet num = currentVal === \"\" ? segment.min : parseInt(currentVal, 10) + 1;\n\t\t\t\t\tif (num > segment.max) num = segment.min;\n\n\t\t\t\t\tconst padded = padValue(num.toString(), segment);\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, padded);\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\n\t\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowDown\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tlet num = currentVal === \"\" ? segment.max : parseInt(currentVal, 10) - 1;\n\t\t\t\t\tif (num < segment.min) num = segment.max;\n\n\t\t\t\t\tconst padded = padValue(num.toString(), segment);\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, padded);\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\n\t\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"Backspace\": {\n\t\t\t\t\tif (currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst prev = getPrevEditable(index);\n\t\t\t\t\t\tif (prev !== null) focusSegment(prev);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"Delete\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, \"\");\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[disabled, segments, segmentValues, getNextEditable, getPrevEditable, focusSegment, padValue, tryFireOnChange]\n\t);\n\n\tconst handleFocus = useCallback(\n\t\t() => (e: React.FocusEvent<HTMLInputElement>) => {\n\t\t\te.target.select();\n\t\t},\n\t\t[]\n\t);\n\n\tconst handleContainerFocus = useCallback(() => {\n\t\tclearTimeout(blurTimeout.current);\n\t\tsetIsFocused(true);\n\t}, []);\n\n\tconst handleContainerBlur = useCallback(() => {\n\t\tblurTimeout.current = window.setTimeout(() => {\n\t\t\tsetIsFocused(false);\n\t\t\t// Откат к последнему валидному значению (из пропса) при потере фокуса\n\t\t\tsetDirtyValues(null);\n\t\t}, 0);\n\t}, []);\n\n\tconst focusFirstEmpty = useCallback(() => {\n\t\tconst firstEmpty = editableIndices.find((i) => !(segmentValues.get(i) ?? \"\"));\n\t\tconst target = firstEmpty ?? editableIndices[editableIndices.length - 1];\n\t\tif (target !== undefined) focusSegment(target);\n\t}, [editableIndices, segmentValues, focusSegment]);\n\n\treturn {\n\t\tsegments,\n\t\tsegmentValues,\n\t\tisFocused,\n\t\tregisterRef,\n\t\thandleInput,\n\t\thandleKeyDown,\n\t\thandleFocus,\n\t\thandleContainerFocus,\n\t\thandleContainerBlur,\n\t\tfocusFirstEmpty\n\t};\n}\n","import { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { InputClearButton, InputControl, InputUI, useInputFieldIds } from \"../input\";\nimport { UiBaseProps } from \"../types\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport styles from \"./InputDateTime.module.scss\";\nimport { useMaskedSegments } from \"./useMaskedSegments\";\n\ninterface InputDateTimeBaseProps extends UiBaseProps<Date, Date | undefined> {\n\tmask: string;\n\n\tclassName?: string;\n\n\terror?: string;\n\tonClearError?: () => void;\n\tonClear?: () => void;\n\n\t\"aria-label\"?: string;\n}\n\nfunction InputDateTimeBase({\n\tmask,\n\tvalue,\n\tonChange,\n\tlabel,\n\tdescription,\n\tdisabled,\n\tsize,\n\tclassName,\n\terror,\n\tonClearError,\n\tonClear,\n\t\"aria-label\": ariaLabel\n}: InputDateTimeBaseProps) {\n\tconst {\n\t\tsegments,\n\t\tsegmentValues,\n\t\tregisterRef,\n\t\thandleInput,\n\t\thandleKeyDown,\n\t\thandleFocus,\n\t\thandleContainerFocus,\n\t\thandleContainerBlur,\n\t\tfocusFirstEmpty\n\t} = useMaskedSegments({ mask, value, onChange, onClearError, disabled });\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!error\n\t});\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={error}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<InputControl\n\t\t\t\tendAdornment={onClear ? <InputClearButton onClick={onClear} disabled={disabled} /> : undefined}\n\t\t\t\tendAdornmentWidth={onClear ? \"var(--control-height)\" : undefined}>\n\t\t\t\t{({ controlClassName }) => (\n\t\t\t\t\t<div\n\t\t\t\t\t\tid={controlId}\n\t\t\t\t\t\tclassName={cn(uiStyles.uiInputControlFake, controlClassName)}\n\t\t\t\t\t\tdata-invalid={error ? \"\" : undefined}\n\t\t\t\t\t\tdata-disabled={disabled || undefined}\n\t\t\t\t\t\trole=\"group\"\n\t\t\t\t\t\taria-invalid={!!error || undefined}\n\t\t\t\t\t\taria-label={ariaLabel || (typeof label === \"string\" ? label : undefined)}\n\t\t\t\t\t\taria-labelledby={ariaLabel ? undefined : labelId}\n\t\t\t\t\t\taria-describedby={describedBy}\n\t\t\t\t\t\tonFocus={handleContainerFocus}\n\t\t\t\t\t\tonBlur={handleContainerBlur}\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\tif (e.target === e.currentTarget) focusFirstEmpty();\n\t\t\t\t\t\t}}>\n\t\t\t\t\t\t{segments.map((segment, index) => {\n\t\t\t\t\t\t\tif (segment.kind === \"literal\") {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<span key={index} className={styles.separator} data-disabled={disabled || undefined}>\n\t\t\t\t\t\t\t\t\t\t{segment.text}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\t\t\tref={registerRef(index)}\n\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\tinputMode=\"numeric\"\n\t\t\t\t\t\t\t\t\tclassName={styles.segmentInput}\n\t\t\t\t\t\t\t\t\tstyle={{ width: `${segment.length + 0.5}ch` }}\n\t\t\t\t\t\t\t\t\tvalue={segmentValues.get(index) ?? \"\"}\n\t\t\t\t\t\t\t\t\tplaceholder={segment.placeholder}\n\t\t\t\t\t\t\t\t\tmaxLength={segment.length}\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\taria-label={segment.type}\n\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\tonChange={handleInput(index)}\n\t\t\t\t\t\t\t\t\tonKeyDown={handleKeyDown(index)}\n\t\t\t\t\t\t\t\t\tonFocus={handleFocus()}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</InputControl>\n\t\t</InputUI>\n\t);\n}\n\nexport type InputDateProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\nexport type InputTimeProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\nexport type InputDateTimeProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\n\nexport function InputDate({ mask = \"YYYY.MM.DD\", ...props }: InputDateProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n\nexport function InputTime({ mask = \"hh:mm\", ...props }: InputTimeProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n\nexport function InputDateTime({ mask = \"YYYY.MM.DD hh:mm\", ...props }: InputDateTimeProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InputDateTime-CxfAFe2L.js","names":[],"sources":["../../src/input-date-time/InputDateTime.module.scss","../../src/input-date-time/maskParser.ts","../../src/input-date-time/useMaskedSegments.ts","../../src/input-date-time/InputDateTime.tsx"],"sourcesContent":["@use \"@/styles/mixins\" as *;\n\n.segmentInput {\n\tborder: none;\n\tbackground: transparent;\n\toutline: none;\n\tpadding: 0;\n\tmargin: 0;\n\tfont-family: var(--font-family-mono);\n\tcolor: inherit;\n\ttext-align: center;\n\tcaret-color: var(--content-0);\n\tfont-variant-numeric: tabular-nums;\n\n\t&::placeholder {\n\t\tcolor: var(--content-2);\n\t\t// font-size: var(--font-size-sm);\n\t}\n\n\t&::selection {\n\t\tbackground-color: var(--focus-ring);\n\t\tcolor: var(--surface-0);\n\t}\n\n\t// Remove spin buttons\n\t&::-webkit-inner-spin-button,\n\t&::-webkit-outer-spin-button {\n\t\t-webkit-appearance: none;\n\t\tmargin: 0;\n\t}\n\n\t&:disabled {\n\t\topacity: 0.25;\n\t}\n}\n\n.separator {\n\tuser-select: none;\n\tcolor: var(--content-2);\n\tflex-shrink: 0;\n\n\t&[data-disabled] {\n\t\topacity: 0.25;\n\t}\n}\n","import {\n\ttype DateMaskSegment,\n\ttype DateSegmentId,\n\tdateToIndexedSegmentValues,\n\ttype EditableDateSegment,\n\tindexedSegmentsToDate,\n\ttype LiteralDateSegment,\n\tparseDateSegmentMask\n} from \"@ryuzaki13/react-foundation-lib/date-segments\";\n\n/**\n * Совместимый тип сегмента для существующего `InputDateTime`.\n */\nexport type SegmentType = DateSegmentId;\n\n/**\n * Совместимый редактируемый сегмент для существующего `InputDateTime`.\n */\nexport interface EditableSegment extends Omit<EditableDateSegment, \"id\"> {\n\ttype: SegmentType;\n}\n\n/**\n * Совместимый литеральный сегмент для существующего `InputDateTime`.\n */\nexport type LiteralSegment = LiteralDateSegment;\n\n/**\n * Совместимый тип сегмента маски для существующего `InputDateTime`.\n */\nexport type Segment = EditableSegment | LiteralSegment;\n\n/**\n * Разбирает строковую маску, сохраняя прежний контракт `InputDateTime`.\n */\nexport function parseMask(mask: string): Segment[] {\n\treturn parseDateSegmentMask(mask).map((segment) => (segment.kind === \"editable\" ? { ...segment, type: segment.id } : segment));\n}\n\n/**\n * Преобразует Date в карту значений сегментов по их совместимым типам.\n */\nexport function dateToSegmentValues(date: Date | undefined, segments: Segment[]): Map<SegmentType, string> {\n\tconst indexedValues = dateToIndexedSegmentValues(date, segments as DateMaskSegment[]);\n\tconst values = new Map<SegmentType, string>();\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind !== \"editable\") return;\n\t\tvalues.set(segment.type, indexedValues.get(index) ?? \"\");\n\t});\n\n\treturn values;\n}\n\n/**\n * Собирает строгий Date из карты сегментов старого формата.\n */\nexport function segmentsToDate(segments: Segment[], values: Map<SegmentType, string>): Date | null {\n\tconst indexedValues = new Map<number, string>();\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind !== \"editable\") return;\n\t\tindexedValues.set(index, values.get(segment.type) ?? \"\");\n\t});\n\n\treturn indexedSegmentsToDate(segments as DateMaskSegment[], indexedValues);\n}\n","import React, { useCallback, useMemo, useRef, useState } from \"react\";\n\nimport { dateToSegmentValues, EditableSegment, parseMask, segmentsToDate, SegmentType } from \"./maskParser\";\n\ninterface UseMaskedSegmentsOptions {\n\tmask: string;\n\tvalue: Date | undefined;\n\tonChange: (date: Date) => void;\n\tonClearError?: () => void;\n\tdisabled?: boolean;\n}\n\n// Вычисляет Map<index, string> из Date и массива сегментов\nfunction buildSegmentMap(date: Date | undefined, segments: ReturnType<typeof parseMask>): Map<number, string> {\n\tconst typeValues = dateToSegmentValues(date, segments);\n\tconst map = new Map<number, string>();\n\n\tsegments.forEach((seg, i) => {\n\t\tif (seg.kind === \"editable\") {\n\t\t\tmap.set(i, typeValues.get(seg.type) ?? \"\");\n\t\t}\n\t});\n\n\treturn map;\n}\n\n// TODO: Duplicate date-time-input/model/useDateTimeSegments\nfunction resolveEditableIndices(segments: ReturnType<typeof parseMask>): number[] {\n\tconst indices: number[] = [];\n\n\tsegments.forEach((segment, index) => {\n\t\tif (segment.kind === \"editable\") {\n\t\t\tindices.push(index);\n\t\t}\n\t});\n\n\treturn indices;\n}\n\nexport function useMaskedSegments({ mask, value, onChange, onClearError, disabled }: UseMaskedSegmentsOptions) {\n\tconst segments = useMemo(() => parseMask(mask), [mask]);\n\n\tconst editableIndices = useMemo(() => resolveEditableIndices(segments), [segments]);\n\n\t// Значения сегментов, вычисленные из пропса value (источник истины)\n\tconst committedValues = useMemo(() => buildSegmentMap(value, segments), [value, segments]);\n\n\t// Локальные «грязные» значения при редактировании (null → используем committedValues)\n\tconst [dirtyValues, setDirtyValues] = useState<Map<number, string> | null>(null);\n\n\t// Сброс грязного состояния при внешнем изменении value (паттерн «adjusting state during render»)\n\tconst [prevValueTime, setPrevValueTime] = useState(() => value?.getTime());\n\tconst currentValueTime = value?.getTime();\n\tif (currentValueTime !== prevValueTime) {\n\t\tsetPrevValueTime(currentValueTime);\n\t\tsetDirtyValues(null);\n\t}\n\n\t// Текущие отображаемые значения\n\tconst segmentValues = dirtyValues ?? committedValues;\n\n\tconst refsMap = useRef<Map<number, HTMLInputElement>>(new Map());\n\tconst blurTimeout = useRef<number>(0);\n\tconst [isFocused, setIsFocused] = useState(false);\n\n\tconst tryFireOnChange = useCallback(\n\t\t(updatedValues: Map<number, string>) => {\n\t\t\tconst typeValues = new Map<SegmentType, string>();\n\n\t\t\tsegments.forEach((seg, i) => {\n\t\t\t\tif (seg.kind === \"editable\") {\n\t\t\t\t\ttypeValues.set(seg.type, updatedValues.get(i) ?? \"\");\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tconst date = segmentsToDate(segments, typeValues);\n\t\t\tif (date !== null) {\n\t\t\t\tonChange(date);\n\t\t\t}\n\t\t},\n\t\t[segments, onChange]\n\t);\n\n\tconst focusSegment = useCallback((index: number, selectAll = true) => {\n\t\tconst el = refsMap.current.get(index);\n\t\tif (el) {\n\t\t\tel.focus();\n\t\t\tif (selectAll) {\n\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t}\n\t\t}\n\t}, []);\n\n\tconst getNextEditable = useCallback(\n\t\t(currentIndex: number): number | null => {\n\t\t\tconst pos = editableIndices.indexOf(currentIndex);\n\t\t\treturn pos < editableIndices.length - 1 ? editableIndices[pos + 1] : null;\n\t\t},\n\t\t[editableIndices]\n\t);\n\n\tconst getPrevEditable = useCallback(\n\t\t(currentIndex: number): number | null => {\n\t\t\tconst pos = editableIndices.indexOf(currentIndex);\n\t\t\treturn pos > 0 ? editableIndices[pos - 1] : null;\n\t\t},\n\t\t[editableIndices]\n\t);\n\n\tconst padValue = useCallback((val: string, segment: EditableSegment): string => {\n\t\treturn val.padStart(segment.length, \"0\");\n\t}, []);\n\n\tconst registerRef = useCallback(\n\t\t(index: number) => (el: HTMLInputElement | null) => {\n\t\t\tif (el) {\n\t\t\t\trefsMap.current.set(index, el);\n\t\t\t} else {\n\t\t\t\trefsMap.current.delete(index);\n\t\t\t}\n\t\t},\n\t\t[]\n\t);\n\n\tconst handleInput = useCallback(\n\t\t(index: number) => (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tif (disabled) return;\n\n\t\t\tconst segment = segments[index] as EditableSegment;\n\t\t\tconst raw = e.target.value.replace(/\\D/g, \"\");\n\t\t\tconst clamped = raw.slice(0, segment.length);\n\n\t\t\tconst updated = new Map(segmentValues);\n\t\t\tupdated.set(index, clamped);\n\t\t\tsetDirtyValues(updated);\n\n\t\t\tonClearError?.();\n\n\t\t\t// Авто-переход к следующему сегменту при заполнении текущего\n\t\t\tif (clamped.length === segment.length) {\n\t\t\t\tconst next = getNextEditable(index);\n\t\t\t\tif (next !== null) {\n\t\t\t\t\trequestAnimationFrame(() => focusSegment(next));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttryFireOnChange(updated);\n\t\t},\n\t\t[disabled, segments, segmentValues, onClearError, getNextEditable, focusSegment, tryFireOnChange]\n\t);\n\n\tconst handleKeyDown = useCallback(\n\t\t(index: number) => (e: React.KeyboardEvent<HTMLInputElement>) => {\n\t\t\tif (disabled) return;\n\n\t\t\tconst segment = segments[index] as EditableSegment;\n\t\t\tconst currentVal = segmentValues.get(index) ?? \"\";\n\t\t\tconst el = e.currentTarget;\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase \"ArrowRight\": {\n\t\t\t\t\tif (el.selectionStart === currentVal.length || currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst next = getNextEditable(index);\n\t\t\t\t\t\tif (next !== null) focusSegment(next);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowLeft\": {\n\t\t\t\t\tif (el.selectionStart === 0 || currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst prev = getPrevEditable(index);\n\t\t\t\t\t\tif (prev !== null) focusSegment(prev);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowUp\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tlet num = currentVal === \"\" ? segment.min : parseInt(currentVal, 10) + 1;\n\t\t\t\t\tif (num > segment.max) num = segment.min;\n\n\t\t\t\t\tconst padded = padValue(num.toString(), segment);\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, padded);\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\n\t\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"ArrowDown\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tlet num = currentVal === \"\" ? segment.max : parseInt(currentVal, 10) - 1;\n\t\t\t\t\tif (num < segment.min) num = segment.max;\n\n\t\t\t\t\tconst padded = padValue(num.toString(), segment);\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, padded);\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\n\t\t\t\t\trequestAnimationFrame(() => el.select());\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"Backspace\": {\n\t\t\t\t\tif (currentVal === \"\") {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tconst prev = getPrevEditable(index);\n\t\t\t\t\t\tif (prev !== null) focusSegment(prev);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase \"Delete\": {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tconst updated = new Map(segmentValues);\n\t\t\t\t\tupdated.set(index, \"\");\n\t\t\t\t\tsetDirtyValues(updated);\n\t\t\t\t\ttryFireOnChange(updated);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[disabled, segments, segmentValues, getNextEditable, getPrevEditable, focusSegment, padValue, tryFireOnChange]\n\t);\n\n\tconst handleFocus = useCallback(\n\t\t() => (e: React.FocusEvent<HTMLInputElement>) => {\n\t\t\te.target.select();\n\t\t},\n\t\t[]\n\t);\n\n\tconst handleContainerFocus = useCallback(() => {\n\t\tclearTimeout(blurTimeout.current);\n\t\tsetIsFocused(true);\n\t}, []);\n\n\tconst handleContainerBlur = useCallback(() => {\n\t\tblurTimeout.current = window.setTimeout(() => {\n\t\t\tsetIsFocused(false);\n\t\t\t// Откат к последнему валидному значению (из пропса) при потере фокуса\n\t\t\tsetDirtyValues(null);\n\t\t}, 0);\n\t}, []);\n\n\tconst focusFirstEmpty = useCallback(() => {\n\t\tconst firstEmpty = editableIndices.find((i) => !(segmentValues.get(i) ?? \"\"));\n\t\tconst target = firstEmpty ?? editableIndices[editableIndices.length - 1];\n\t\tif (target !== undefined) focusSegment(target);\n\t}, [editableIndices, segmentValues, focusSegment]);\n\n\treturn {\n\t\tsegments,\n\t\tsegmentValues,\n\t\tisFocused,\n\t\tregisterRef,\n\t\thandleInput,\n\t\thandleKeyDown,\n\t\thandleFocus,\n\t\thandleContainerFocus,\n\t\thandleContainerBlur,\n\t\tfocusFirstEmpty\n\t};\n}\n","import { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { InputClearButton, InputControl, InputUI, useInputFieldIds } from \"../input\";\nimport { UiBaseProps } from \"../types\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport styles from \"./InputDateTime.module.scss\";\nimport { useMaskedSegments } from \"./useMaskedSegments\";\n\ninterface InputDateTimeBaseProps extends UiBaseProps<Date, Date | undefined> {\n\tmask: string;\n\n\tclassName?: string;\n\n\terror?: string;\n\tonClearError?: () => void;\n\tonClear?: () => void;\n\n\t\"aria-label\"?: string;\n}\n\nfunction InputDateTimeBase({\n\tmask,\n\tvalue,\n\tonChange,\n\tlabel,\n\tdescription,\n\tdisabled,\n\tsize,\n\tclassName,\n\terror,\n\tonClearError,\n\tonClear,\n\t\"aria-label\": ariaLabel\n}: InputDateTimeBaseProps) {\n\tconst {\n\t\tsegments,\n\t\tsegmentValues,\n\t\tregisterRef,\n\t\thandleInput,\n\t\thandleKeyDown,\n\t\thandleFocus,\n\t\thandleContainerFocus,\n\t\thandleContainerBlur,\n\t\tfocusFirstEmpty\n\t} = useMaskedSegments({ mask, value, onChange, onClearError, disabled });\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!error\n\t});\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={error}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<InputControl\n\t\t\t\tendAdornment={onClear ? <InputClearButton onClick={onClear} disabled={disabled} /> : undefined}\n\t\t\t\tendAdornmentWidth={onClear ? \"var(--control-height)\" : undefined}>\n\t\t\t\t{({ controlClassName }) => (\n\t\t\t\t\t<div\n\t\t\t\t\t\tid={controlId}\n\t\t\t\t\t\tclassName={cn(uiStyles.uiInputControlFake, controlClassName)}\n\t\t\t\t\t\tdata-invalid={error ? \"\" : undefined}\n\t\t\t\t\t\tdata-disabled={disabled || undefined}\n\t\t\t\t\t\trole=\"group\"\n\t\t\t\t\t\taria-invalid={!!error || undefined}\n\t\t\t\t\t\taria-label={ariaLabel || (typeof label === \"string\" ? label : undefined)}\n\t\t\t\t\t\taria-labelledby={ariaLabel ? undefined : labelId}\n\t\t\t\t\t\taria-describedby={describedBy}\n\t\t\t\t\t\tonFocus={handleContainerFocus}\n\t\t\t\t\t\tonBlur={handleContainerBlur}\n\t\t\t\t\t\tonClick={(e) => {\n\t\t\t\t\t\t\tif (e.target === e.currentTarget) focusFirstEmpty();\n\t\t\t\t\t\t}}>\n\t\t\t\t\t\t{segments.map((segment, index) => {\n\t\t\t\t\t\t\tif (segment.kind === \"literal\") {\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<span key={index} className={styles.separator} data-disabled={disabled || undefined}>\n\t\t\t\t\t\t\t\t\t\t{segment.text}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tkey={index}\n\t\t\t\t\t\t\t\t\tref={registerRef(index)}\n\t\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\t\tinputMode=\"numeric\"\n\t\t\t\t\t\t\t\t\tclassName={styles.segmentInput}\n\t\t\t\t\t\t\t\t\tstyle={{ width: `${segment.length + 0.5}ch` }}\n\t\t\t\t\t\t\t\t\tvalue={segmentValues.get(index) ?? \"\"}\n\t\t\t\t\t\t\t\t\tplaceholder={segment.placeholder}\n\t\t\t\t\t\t\t\t\tmaxLength={segment.length}\n\t\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\t\taria-label={segment.type}\n\t\t\t\t\t\t\t\t\tautoComplete=\"off\"\n\t\t\t\t\t\t\t\t\tonChange={handleInput(index)}\n\t\t\t\t\t\t\t\t\tonKeyDown={handleKeyDown(index)}\n\t\t\t\t\t\t\t\t\tonFocus={handleFocus()}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</InputControl>\n\t\t</InputUI>\n\t);\n}\n\nexport type InputDateProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\nexport type InputTimeProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\nexport type InputDateTimeProps = Omit<InputDateTimeBaseProps, \"mask\"> & { mask?: string };\n\nexport function InputDate({ mask = \"YYYY.MM.DD\", ...props }: InputDateProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n\nexport function InputTime({ mask = \"hh:mm\", ...props }: InputTimeProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n\nexport function InputDateTime({ mask = \"YYYY.MM.DD hh:mm\", ...props }: InputDateTimeProps) {\n\treturn <InputDateTimeBase mask={mask} {...props} />;\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as e } from "./ui.module-BisoTevy.js";
|
|
2
|
-
import { c as t, n, o as r, r as i } from "./Input-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { c as t, n, o as r, r as i } from "./Input-BmjlpA09.js";
|
|
3
|
+
import { useCallback as a, useRef as o } from "react";
|
|
4
|
+
import { cn as s, handleKeyboardActivation as c } from "@ryuzaki13/react-foundation-lib/utils";
|
|
5
|
+
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
6
6
|
import { ReadFileError as d, assertValidAccept as f, assertValidAllowedMime as p, readFile as m } from "@ryuzaki13/react-foundation-lib/file";
|
|
7
7
|
var h = {
|
|
8
8
|
control: "Ggxyuj",
|
|
@@ -14,11 +14,11 @@ var h = {
|
|
|
14
14
|
function g(g) {
|
|
15
15
|
let { value: _, onClear: v, onReadError: y, accept: b, allowedMime: x, maxBytes: S, label: C, description: w, placeholder: T = "Выберите файл", disabled: E, size: D, error: O, onClearError: k, className: A } = g;
|
|
16
16
|
p(x), f(b);
|
|
17
|
-
let j =
|
|
17
|
+
let j = o(null), { controlId: M, labelId: N, descriptionId: P, errorId: F, describedBy: I } = t({
|
|
18
18
|
hasLabel: C != null,
|
|
19
19
|
hasDescription: !!w,
|
|
20
20
|
hasError: !!O
|
|
21
|
-
}), L =
|
|
21
|
+
}), L = a(async (e) => {
|
|
22
22
|
let t = e.target.files?.[0];
|
|
23
23
|
if (t) {
|
|
24
24
|
e.target.value = "", O && k && k();
|
|
@@ -48,10 +48,10 @@ function g(g) {
|
|
|
48
48
|
y,
|
|
49
49
|
O,
|
|
50
50
|
k
|
|
51
|
-
]), R =
|
|
51
|
+
]), R = a(() => {
|
|
52
52
|
j.current?.click();
|
|
53
53
|
}, []);
|
|
54
|
-
return /* @__PURE__ */
|
|
54
|
+
return /* @__PURE__ */ u(r, {
|
|
55
55
|
label: C,
|
|
56
56
|
description: w,
|
|
57
57
|
disabled: E,
|
|
@@ -62,7 +62,7 @@ function g(g) {
|
|
|
62
62
|
labelId: N,
|
|
63
63
|
descriptionId: P,
|
|
64
64
|
errorId: F,
|
|
65
|
-
children: [/* @__PURE__ */
|
|
65
|
+
children: [/* @__PURE__ */ l("input", {
|
|
66
66
|
ref: j,
|
|
67
67
|
id: M,
|
|
68
68
|
type: "file",
|
|
@@ -71,27 +71,27 @@ function g(g) {
|
|
|
71
71
|
className: h.hiddenInput,
|
|
72
72
|
onChange: L,
|
|
73
73
|
tabIndex: -1
|
|
74
|
-
}), /* @__PURE__ */
|
|
75
|
-
endAdornment: v ? /* @__PURE__ */
|
|
74
|
+
}), /* @__PURE__ */ l(i, {
|
|
75
|
+
endAdornment: v ? /* @__PURE__ */ l(n, {
|
|
76
76
|
onClick: v,
|
|
77
77
|
disabled: E
|
|
78
78
|
}) : void 0,
|
|
79
79
|
endAdornmentWidth: v ? "var(--control-height)" : void 0,
|
|
80
|
-
children: ({ controlClassName: t }) => /* @__PURE__ */
|
|
80
|
+
children: ({ controlClassName: t }) => /* @__PURE__ */ l("div", {
|
|
81
81
|
role: "button",
|
|
82
82
|
tabIndex: E ? -1 : 0,
|
|
83
83
|
onClick: R,
|
|
84
|
-
onKeyDown: (e) =>
|
|
85
|
-
className:
|
|
84
|
+
onKeyDown: (e) => c(e, R, { disabled: E }),
|
|
85
|
+
className: s(e.uiInputControl, h.control, t, !!O && e.invalid),
|
|
86
86
|
"data-disabled": E || void 0,
|
|
87
87
|
"aria-invalid": !!O || void 0,
|
|
88
88
|
"aria-disabled": E,
|
|
89
89
|
"aria-labelledby": N,
|
|
90
90
|
"aria-describedby": I,
|
|
91
|
-
children: _ ? /* @__PURE__ */
|
|
91
|
+
children: _ ? /* @__PURE__ */ l("span", {
|
|
92
92
|
className: h.fileName,
|
|
93
93
|
children: _.meta.name
|
|
94
|
-
}) : /* @__PURE__ */
|
|
94
|
+
}) : /* @__PURE__ */ l("span", {
|
|
95
95
|
className: e.uiPlaceholder,
|
|
96
96
|
children: T
|
|
97
97
|
})
|
|
@@ -102,4 +102,4 @@ function g(g) {
|
|
|
102
102
|
//#endregion
|
|
103
103
|
export { g as t };
|
|
104
104
|
|
|
105
|
-
//# sourceMappingURL=InputFile-
|
|
105
|
+
//# sourceMappingURL=InputFile-CyZu__B_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InputFile-CyZu__B_.js","names":[],"sources":["../../src/input-file/InputFile.module.scss","../../src/input-file/InputFile.tsx"],"sourcesContent":[".control {\n\theight: var(--control-height);\n\twidth: 100%;\n\tpadding: 0 var(--space-sm);\n\tfont-size: var(--font-size-md);\n\tcursor: pointer;\n\tdisplay: flex;\n\talign-items: center;\n}\n\n.fileName {\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.hiddenInput {\n\tposition: absolute;\n\twidth: 0;\n\theight: 0;\n\topacity: 0;\n\toverflow: hidden;\n\tpointer-events: none;\n}\n","import { useCallback, useRef } from \"react\";\n\nimport {\n\tassertValidAccept,\n\tassertValidAllowedMime,\n\treadFile,\n\tReadFileError,\n\tReadFileResult,\n\tReadMode\n} from \"@ryuzaki13/react-foundation-lib/file\";\nimport { cn, handleKeyboardActivation } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { InputClearButton, InputControl, InputUI, useInputFieldIds } from \"../input\";\nimport { UiBaseProps } from \"../types\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport styles from \"./InputFile.module.scss\";\n\ninterface InputFileCommonProps extends Omit<UiBaseProps<undefined>, \"value\" | \"onChange\"> {\n\t/** Callback очистки выбранного файла. Если передан — отображается кнопка «крестик» */\n\tonClear?: () => void;\n\t/** Callback ошибки чтения файла (невалидный MIME, превышение размера и т.д.) */\n\tonReadError?: (error: ReadFileError) => void;\n\n\t/** HTML-атрибут accept для нативного input[type=\"file\"] (например `[\".pdf\", \".docx\"]`) */\n\taccept?: readonly string[];\n\t/** Список допустимых MIME-типов — передаётся в readFile для валидации */\n\tallowedMime?: readonly string[];\n\t/** Максимальный размер файла в байтах — передаётся в readFile для валидации */\n\tmaxBytes?: number;\n\t/** Режим чтения файла: \"data-url\" (по умолчанию) или \"array-buffer\" */\n\treadMode?: ReadMode;\n\n\t/** Текст ошибки под полем */\n\terror?: string;\n\t/** Callback сброса ошибки (вызывается при повторном выборе файла) */\n\tonClearError?: () => void;\n\t/** CSS-класс обёртки */\n\tclassName?: string;\n}\n\ntype InputFileDataUrlResult = Extract<ReadFileResult, { mode: \"data-url\" }>;\ntype InputFileArrayBufferResult = Extract<ReadFileResult, { mode: \"array-buffer\" }>;\n\n/**\n * Пропсы компонента InputFile.\n *\n * Компонент предназначен для выбора одного файла.\n * Внешний вид идентичен InputText — label, description, error, кнопка очистки.\n *\n * В onChange передаётся результат чтения файла через readFile:\n * - В режиме \"data-url\" — объект с dataUrl и метаданными\n * - В режиме \"array-buffer\" — объект с ArrayBuffer и метаданными\n */\nexport type InputFileProps =\n\t| (InputFileCommonProps & {\n\t\t\tvalue: ReadFileResult | undefined;\n\t\t\tonChange: (value: InputFileDataUrlResult) => void;\n\t\t\treadMode?: \"data-url\";\n\t })\n\t| (InputFileCommonProps & {\n\t\t\tvalue: ReadFileResult | undefined;\n\t\t\tonChange: (value: InputFileArrayBufferResult) => void;\n\t\t\treadMode: \"array-buffer\";\n\t });\n\n/**\n * InputFile — компонент выбора одного файла.\n *\n * Визуально идентичен InputText: поле с label, description, placeholder,\n * кнопкой очистки (крестик) и блоком ошибки.\n *\n * При клике открывается нативный диалог выбора файла.\n * После выбора файл читается через readFile, результат передаётся в onChange.\n *\n * InputFile позволяет выбрать один файл и передаёт наружу типизированный результат чтения.\n * Если `readMode` не задан или равен `\"data-url\"`, в `onChange` приходит объект с `dataUrl`.\n * Если `readMode` равен `\"array-buffer\"`, в `onChange` приходит объект с `buffer`.\n */\nexport function InputFile(props: InputFileProps) {\n\tconst {\n\t\tvalue,\n\t\tonClear,\n\t\tonReadError,\n\t\taccept,\n\t\tallowedMime,\n\t\tmaxBytes,\n\t\tlabel,\n\t\tdescription,\n\t\tplaceholder = \"Выберите файл\",\n\t\tdisabled,\n\t\tsize,\n\t\terror,\n\t\tonClearError,\n\t\tclassName\n\t} = props;\n\n\tassertValidAllowedMime(allowedMime);\n\tassertValidAccept(accept);\n\n\t/** Реф на скрытый нативный input[type=\"file\"] */\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!error\n\t});\n\n\t/**\n\t * Обработчик выбора файла из нативного диалога.\n\t * Читает файл через readFile и передаёт результат в onChange.\n\t * При ошибке чтения вызывает onReadError.\n\t */\n\tconst handleChange = useCallback(\n\t\tasync (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst file = e.target.files?.[0];\n\t\t\tif (!file) return;\n\n\t\t\t// Сбрасываем значение input чтобы можно было выбрать тот же файл повторно\n\t\t\te.target.value = \"\";\n\n\t\t\t// Сбрасываем ошибку при повторном выборе\n\t\t\tif (error && onClearError) onClearError();\n\n\t\t\ttry {\n\t\t\t\tif (props.readMode === \"array-buffer\") {\n\t\t\t\t\tconst result = await readFile(file, { allowedMime, maxBytes, mode: \"array-buffer\" });\n\t\t\t\t\tprops.onChange(result);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst result = await readFile(file, { allowedMime, maxBytes });\n\t\t\t\tprops.onChange(result);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof ReadFileError && onReadError) {\n\t\t\t\t\tonReadError(err);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[props, allowedMime, maxBytes, onReadError, error, onClearError]\n\t);\n\n\t/** Клик по видимому контролу открывает нативный диалог */\n\tconst handleClick = useCallback(() => {\n\t\tinputRef.current?.click();\n\t}, []);\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={error}\n\t\t\tcontrolId={controlId}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<input\n\t\t\t\tref={inputRef}\n\t\t\t\tid={controlId}\n\t\t\t\ttype=\"file\"\n\t\t\t\taccept={(accept ?? allowedMime)?.join(\",\")}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tclassName={styles.hiddenInput}\n\t\t\t\tonChange={handleChange}\n\t\t\t\ttabIndex={-1}\n\t\t\t/>\n\n\t\t\t<InputControl\n\t\t\t\tendAdornment={onClear ? <InputClearButton onClick={onClear} disabled={disabled} /> : undefined}\n\t\t\t\tendAdornmentWidth={onClear ? \"var(--control-height)\" : undefined}>\n\t\t\t\t{({ controlClassName }) => (\n\t\t\t\t\t<div\n\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\ttabIndex={disabled ? -1 : 0}\n\t\t\t\t\t\tonClick={handleClick}\n\t\t\t\t\t\tonKeyDown={(event) => handleKeyboardActivation(event, handleClick, { disabled })}\n\t\t\t\t\t\tclassName={cn(uiStyles.uiInputControl, styles.control, controlClassName, !!error && uiStyles.invalid)}\n\t\t\t\t\t\tdata-disabled={disabled || undefined}\n\t\t\t\t\t\taria-invalid={!!error || undefined}\n\t\t\t\t\t\taria-disabled={disabled}\n\t\t\t\t\t\taria-labelledby={labelId}\n\t\t\t\t\t\taria-describedby={describedBy}>\n\t\t\t\t\t\t{value ? (\n\t\t\t\t\t\t\t<span className={styles.fileName}>{value.meta.name}</span>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span className={uiStyles.uiPlaceholder}>{placeholder}</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</InputControl>\n\t\t</InputUI>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;AC+EA,SAAgB,EAAU,GAAuB;CAChD,IAAM,EACL,UACA,YACA,gBACA,WACA,gBACA,aACA,UACA,gBACA,iBAAc,iBACd,aACA,SACA,UACA,iBACA,iBACG;CAGJ,AADA,EAAuB,CAAW,GAClC,EAAkB,CAAM;CAGxB,IAAM,IAAW,EAAyB,IAAI,GACxC,EAAE,cAAW,YAAS,kBAAe,YAAS,mBAAgB,EAAiB;EACpF,UAAU,KAAiC;EAC3C,gBAAgB,CAAC,CAAC;EAClB,UAAU,CAAC,CAAC;CACb,CAAC,GAOK,IAAe,EACpB,OAAO,MAA2C;EACjD,IAAM,IAAO,EAAE,OAAO,QAAQ;EACzB,OAML;GAHA,EAAE,OAAO,QAAQ,IAGb,KAAS,KAAc,EAAa;GAExC,IAAI;IACH,IAAI,EAAM,aAAa,gBAAgB;KACtC,IAAM,IAAS,MAAM,EAAS,GAAM;MAAE;MAAa;MAAU,MAAM;KAAe,CAAC;KACnF,EAAM,SAAS,CAAM;KACrB;IACD;IAEA,IAAM,IAAS,MAAM,EAAS,GAAM;KAAE;KAAa;IAAS,CAAC;IAC7D,EAAM,SAAS,CAAM;GACtB,SAAS,GAAK;IACb,AAAI,aAAe,KAAiB,KACnC,EAAY,CAAG;GAEjB;EAfwC;CAgBzC,GACA;EAAC;EAAO;EAAa;EAAU;EAAa;EAAO;CAAY,CAChE,GAGM,IAAc,QAAkB;EACrC,EAAS,SAAS,MAAM;CACzB,GAAG,CAAC,CAAC;CAEL,OACC,kBAAC,GAAD;EACQ;EACM;EACH;EACC;EACL;EACC;EACI;EACF;EACM;EACN;YAVV,CAWC,kBAAC,SAAD;GACC,KAAK;GACL,IAAI;GACJ,MAAK;GACL,SAAS,KAAU,EAAA,EAAc,KAAK,GAAG;GAC/B;GACV,WAAW,EAAO;GAClB,UAAU;GACV,UAAU;EACV,CAAA,GAED,kBAAC,GAAD;GACC,cAAc,IAAU,kBAAC,GAAD;IAAkB,SAAS;IAAmB;GAAW,CAAA,IAAI,KAAA;GACrF,mBAAmB,IAAU,0BAA0B,KAAA;cACrD,EAAE,0BACH,kBAAC,OAAD;IACC,MAAK;IACL,UAAU,IAAW,KAAK;IAC1B,SAAS;IACT,YAAY,MAAU,EAAyB,GAAO,GAAa,EAAE,YAAS,CAAC;IAC/E,WAAW,EAAG,EAAS,gBAAgB,EAAO,SAAS,GAAkB,CAAC,CAAC,KAAS,EAAS,OAAO;IACpG,iBAAe,KAAY,KAAA;IAC3B,gBAAc,CAAC,CAAC,KAAS,KAAA;IACzB,iBAAe;IACf,mBAAiB;IACjB,oBAAkB;cACjB,IACA,kBAAC,QAAD;KAAM,WAAW,EAAO;eAAW,EAAM,KAAK;IAAW,CAAA,IAEzD,kBAAC,QAAD;KAAM,WAAW,EAAS;eAAgB;IAAkB,CAAA;GAEzD,CAAA;EAEO,CAAA,CACN;;AAEX"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as e } from "./ui.module-BisoTevy.js";
|
|
2
|
-
import { c as t, o as n, r } from "./Input-
|
|
3
|
-
import {
|
|
4
|
-
import { cn as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import { c as t, o as n, r } from "./Input-BmjlpA09.js";
|
|
3
|
+
import { useCallback as i, useRef as a } from "react";
|
|
4
|
+
import { cn as o, handleKeyboardActivation as s } from "@ryuzaki13/react-foundation-lib/utils";
|
|
5
|
+
import { XIcon as c } from "lucide-react";
|
|
6
|
+
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
7
7
|
import { ReadFileError as d, assertValidAccept as f, assertValidAllowedMime as p, readFile as m } from "@ryuzaki13/react-foundation-lib/file";
|
|
8
8
|
var h = {
|
|
9
9
|
control: "h9SMea",
|
|
@@ -16,44 +16,44 @@ var h = {
|
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/input-files/InputFilesList.tsx
|
|
18
18
|
function g({ files: e, onChange: t }) {
|
|
19
|
-
let n =
|
|
19
|
+
let n = i((n) => {
|
|
20
20
|
t(e.filter((e, t) => t !== n));
|
|
21
21
|
}, [e, t]);
|
|
22
|
-
return !e || !e.length ? null : /* @__PURE__ */
|
|
22
|
+
return !e || !e.length ? null : /* @__PURE__ */ l("ul", {
|
|
23
23
|
className: h.fileList,
|
|
24
|
-
children: e.map((e, t) => /* @__PURE__ */
|
|
24
|
+
children: e.map((e, t) => /* @__PURE__ */ u("li", {
|
|
25
25
|
className: h.fileItem,
|
|
26
|
-
children: [/* @__PURE__ */
|
|
26
|
+
children: [/* @__PURE__ */ l("span", {
|
|
27
27
|
className: h.fileItemName,
|
|
28
28
|
children: e.meta.name
|
|
29
|
-
}), /* @__PURE__ */
|
|
29
|
+
}), /* @__PURE__ */ l("button", {
|
|
30
30
|
type: "button",
|
|
31
|
-
className:
|
|
31
|
+
className: o(h.removeButton, "flexCenter"),
|
|
32
32
|
onClick: () => n(t),
|
|
33
33
|
"aria-label": `Удалить ${e.meta.name}`,
|
|
34
|
-
children: /* @__PURE__ */
|
|
34
|
+
children: /* @__PURE__ */ l(c, {})
|
|
35
35
|
})]
|
|
36
36
|
}, `${e.meta.name}-${e.meta.lastModified}`))
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
//#endregion
|
|
40
40
|
//#region src/input-files/InputFiles.tsx
|
|
41
|
-
function _(
|
|
42
|
-
let { value: _, onReadError: v, accept: y, allowedMime: b, maxBytes: x, maxFiles: S, label: C, description: w, placeholder: T = "Выберите файлы", disabled: E, size: D, error: O, onClearError: k, className: A } =
|
|
41
|
+
function _(c) {
|
|
42
|
+
let { value: _, onReadError: v, accept: y, allowedMime: b, maxBytes: x, maxFiles: S, label: C, description: w, placeholder: T = "Выберите файлы", disabled: E, size: D, error: O, onClearError: k, className: A } = c;
|
|
43
43
|
p(b), f(y);
|
|
44
|
-
let j =
|
|
44
|
+
let j = a(null), { controlId: M, labelId: N, descriptionId: P, errorId: F, describedBy: I } = t({
|
|
45
45
|
hasLabel: C != null,
|
|
46
46
|
hasDescription: !!w,
|
|
47
47
|
hasError: !!O
|
|
48
|
-
}), L = typeof S == "number" && _.length >= S, R =
|
|
48
|
+
}), L = typeof S == "number" && _.length >= S, R = i(async (e) => {
|
|
49
49
|
let t = e.target.files;
|
|
50
50
|
if (!t || t.length === 0) return;
|
|
51
51
|
let n = Array.from(t);
|
|
52
52
|
e.target.value = "", O && k && k();
|
|
53
|
-
let r = typeof S == "number" ? S - _.length : n.length,
|
|
54
|
-
if (
|
|
53
|
+
let r = typeof S == "number" ? S - _.length : n.length, i = n.slice(0, r);
|
|
54
|
+
if (c.readMode === "array-buffer") {
|
|
55
55
|
let e = [];
|
|
56
|
-
for (let t of
|
|
56
|
+
for (let t of i) try {
|
|
57
57
|
let n = await m(t, {
|
|
58
58
|
allowedMime: b,
|
|
59
59
|
maxBytes: x,
|
|
@@ -63,22 +63,22 @@ function _(i) {
|
|
|
63
63
|
} catch (e) {
|
|
64
64
|
e instanceof d && v && v(e);
|
|
65
65
|
}
|
|
66
|
-
e.length > 0 &&
|
|
66
|
+
e.length > 0 && c.onChange([...c.value, ...e]);
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
|
-
let
|
|
70
|
-
for (let e of
|
|
69
|
+
let a = [];
|
|
70
|
+
for (let e of i) try {
|
|
71
71
|
let t = await m(e, {
|
|
72
72
|
allowedMime: b,
|
|
73
73
|
maxBytes: x
|
|
74
74
|
});
|
|
75
|
-
|
|
75
|
+
a.push(t);
|
|
76
76
|
} catch (e) {
|
|
77
77
|
e instanceof d && v && v(e);
|
|
78
78
|
}
|
|
79
|
-
|
|
79
|
+
a.length > 0 && c.onChange([...c.value, ...a]);
|
|
80
80
|
}, [
|
|
81
|
-
|
|
81
|
+
c,
|
|
82
82
|
S,
|
|
83
83
|
_.length,
|
|
84
84
|
b,
|
|
@@ -86,13 +86,13 @@ function _(i) {
|
|
|
86
86
|
v,
|
|
87
87
|
O,
|
|
88
88
|
k
|
|
89
|
-
]), z =
|
|
89
|
+
]), z = i(() => {
|
|
90
90
|
j.current?.click();
|
|
91
|
-
}, []), B = (
|
|
92
|
-
files:
|
|
93
|
-
onChange:
|
|
91
|
+
}, []), B = (c.readMode, /* @__PURE__ */ l(g, {
|
|
92
|
+
files: c.value,
|
|
93
|
+
onChange: c.onChange
|
|
94
94
|
}));
|
|
95
|
-
return /* @__PURE__ */
|
|
95
|
+
return /* @__PURE__ */ u(n, {
|
|
96
96
|
label: C,
|
|
97
97
|
description: w,
|
|
98
98
|
disabled: E,
|
|
@@ -104,7 +104,7 @@ function _(i) {
|
|
|
104
104
|
descriptionId: P,
|
|
105
105
|
errorId: F,
|
|
106
106
|
children: [
|
|
107
|
-
/* @__PURE__ */
|
|
107
|
+
/* @__PURE__ */ l("input", {
|
|
108
108
|
ref: j,
|
|
109
109
|
id: M,
|
|
110
110
|
type: "file",
|
|
@@ -115,18 +115,18 @@ function _(i) {
|
|
|
115
115
|
onChange: R,
|
|
116
116
|
tabIndex: -1
|
|
117
117
|
}),
|
|
118
|
-
/* @__PURE__ */
|
|
118
|
+
/* @__PURE__ */ l(r, { children: () => /* @__PURE__ */ l("div", {
|
|
119
119
|
role: "button",
|
|
120
120
|
tabIndex: E || L ? -1 : 0,
|
|
121
121
|
onClick: z,
|
|
122
|
-
onKeyDown: (e) =>
|
|
123
|
-
className:
|
|
122
|
+
onKeyDown: (e) => s(e, z, { disabled: E || L }),
|
|
123
|
+
className: o(e.uiInputControl, h.control, !!O && "invalid"),
|
|
124
124
|
"data-disabled": E || void 0,
|
|
125
125
|
"aria-invalid": !!O || void 0,
|
|
126
126
|
"aria-disabled": E || L,
|
|
127
127
|
"aria-labelledby": N,
|
|
128
128
|
"aria-describedby": I,
|
|
129
|
-
children: /* @__PURE__ */
|
|
129
|
+
children: /* @__PURE__ */ l("span", {
|
|
130
130
|
className: e.uiPlaceholder,
|
|
131
131
|
children: L ? `Максимум ${S} файлов` : T
|
|
132
132
|
})
|
|
@@ -138,4 +138,4 @@ function _(i) {
|
|
|
138
138
|
//#endregion
|
|
139
139
|
export { g as n, _ as t };
|
|
140
140
|
|
|
141
|
-
//# sourceMappingURL=InputFiles-
|
|
141
|
+
//# sourceMappingURL=InputFiles-CrTJV27R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InputFiles-CrTJV27R.js","names":[],"sources":["../../src/input-files/InputFiles.module.scss","../../src/input-files/InputFilesList.tsx","../../src/input-files/InputFiles.tsx"],"sourcesContent":["/* Контрол, имитирующий внешний вид InputText */\n.control {\n\theight: var(--control-height);\n\twidth: 100%;\n\tpadding: 0 var(--space-sm);\n\tfont-size: var(--font-size-md);\n\tcursor: pointer;\n\n\tdisplay: flex;\n\talign-items: center;\n}\n\n/* Скрытый нативный input[type=\"file\"] */\n.hiddenInput {\n\tposition: absolute;\n\twidth: 0;\n\theight: 0;\n\topacity: 0;\n\toverflow: hidden;\n\tpointer-events: none;\n}\n\n/* Список выбранных файлов */\n.fileList {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: var(--space-xs);\n\tmargin-top: var(--space-xs);\n}\n\n/* Элемент списка — строка с именем файла и кнопкой удаления */\n.fileItem {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: var(--space-xs);\n\tpadding: var(--space-xs) var(--space-sm);\n\tbackground-color: var(--surface-2);\n\tborder-radius: var(--radius-sm);\n\t// font-size: var(--font-size-sm);\n}\n\n/* Имя файла — обрезка с троеточием */\n.fileItemName {\n\tflex: 1;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n/* Кнопка удаления файла из списка */\n.removeButton {\n\tflex-shrink: 0;\n\twidth: 1.25em;\n\theight: 1.25em;\n\tcolor: var(--content-2);\n\n\t&:hover {\n\t\tcolor: var(--content-accent);\n\t}\n}\n","import { useCallback } from \"react\";\n\nimport { ReadFileResult } from \"@ryuzaki13/react-foundation-lib/file\";\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { XIcon } from \"lucide-react\";\n\nimport styles from \"./InputFiles.module.scss\";\n\ninterface InputFilesListProps<TFile extends ReadFileResult> {\n\tfiles: TFile[];\n\tonChange: (files: TFile[]) => void;\n}\n\nexport function InputFilesList<TFile extends ReadFileResult>({ files, onChange }: InputFilesListProps<TFile>) {\n\tconst handleRemove = useCallback(\n\t\t(index: number) => {\n\t\t\tonChange(files.filter((_, i) => i !== index));\n\t\t},\n\t\t[files, onChange]\n\t);\n\n\tif (!files || !files.length) return null;\n\n\treturn (\n\t\t<ul className={styles.fileList}>\n\t\t\t{files.map((item, index) => (\n\t\t\t\t<li key={`${item.meta.name}-${item.meta.lastModified}`} className={styles.fileItem}>\n\t\t\t\t\t<span className={styles.fileItemName}>{item.meta.name}</span>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName={cn(styles.removeButton, \"flexCenter\")}\n\t\t\t\t\t\tonClick={() => handleRemove(index)}\n\t\t\t\t\t\taria-label={`Удалить ${item.meta.name}`}>\n\t\t\t\t\t\t<XIcon />\n\t\t\t\t\t</button>\n\t\t\t\t</li>\n\t\t\t))}\n\t\t</ul>\n\t);\n}\n","import { useCallback, useRef } from \"react\";\n\nimport { assertValidAccept, assertValidAllowedMime, readFile, ReadFileError, ReadFileResult } from \"@ryuzaki13/react-foundation-lib/file\";\nimport { cn, handleKeyboardActivation } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { InputControl, InputUI, useInputFieldIds } from \"../input\";\nimport { UiBaseProps } from \"../types\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport styles from \"./InputFiles.module.scss\";\nimport { InputFilesList } from \"./InputFilesList\";\n\ninterface InputFilesCommonProps extends Omit<UiBaseProps<undefined>, \"value\" | \"onChange\"> {\n\t/** Callback ошибки чтения файла */\n\tonReadError?: (error: ReadFileError) => void;\n\n\t/** HTML-атрибут accept для нативного input[type=\"file\"] (например `[\".pdf\", \".docx\"]`) */\n\taccept?: readonly string[];\n\t/** Список допустимых MIME-типов — передаётся в readFile */\n\tallowedMime?: readonly string[];\n\t/** Максимальный размер одного файла в байтах */\n\tmaxBytes?: number;\n\t/** Максимальное количество файлов. При достижении лимита input блокируется */\n\tmaxFiles?: number;\n\n\t/** Текст ошибки под полем */\n\terror?: string;\n\t/** Callback сброса ошибки */\n\tonClearError?: () => void;\n\t/** CSS-класс обёртки */\n\tclassName?: string;\n}\n\ntype InputFilesDataUrlResult = Extract<ReadFileResult, { mode: \"data-url\" }>;\ntype InputFilesArrayBufferResult = Extract<ReadFileResult, { mode: \"array-buffer\" }>;\n\n/**\n * Пропсы компонента InputFiles.\n *\n * Компонент предназначен для выбора нескольких файлов.\n * Выбранные файлы отображаются списком под полем ввода,\n * каждый с кнопкой удаления (крестик).\n *\n * В onChange передаётся обновлённый массив результатов readFile.\n */\nexport type InputFilesProps =\n\t| (InputFilesCommonProps & {\n\t\t\tvalue: InputFilesDataUrlResult[];\n\t\t\tonChange: (value: InputFilesDataUrlResult[]) => void;\n\t\t\t/** Режим чтения: \"data-url\" по умолчанию */\n\t\t\treadMode?: \"data-url\";\n\t })\n\t| (InputFilesCommonProps & {\n\t\t\tvalue: InputFilesArrayBufferResult[];\n\t\t\tonChange: (value: InputFilesArrayBufferResult[]) => void;\n\t\t\t/** Режим чтения файла как ArrayBuffer */\n\t\t\treadMode: \"array-buffer\";\n\t });\n\n/**\n * InputFiles — компонент выбора нескольких файлов.\n *\n * Поле стилизовано как InputText. При клике открывается нативный\n * диалог с multiple. Каждый выбранный файл читается через readFile\n * и добавляется в массив value.\n *\n * Список выбранных файлов отображается под полем.\n * Каждый файл можно удалить кнопкой «крестик».\n *\n * InputFiles типизирует массив по `readMode`.\n * Если `readMode` не задан или равен `\"data-url\"`, в `value` и `onChange`\n * используется массив объектов с `dataUrl`. Если `readMode` равен\n * `\"array-buffer\"`, используется массив объектов с `buffer`.\n */\nexport function InputFiles(props: InputFilesProps) {\n\tconst {\n\t\tvalue,\n\t\tonReadError,\n\t\taccept,\n\t\tallowedMime,\n\t\tmaxBytes,\n\t\tmaxFiles,\n\t\tlabel,\n\t\tdescription,\n\t\tplaceholder = \"Выберите файлы\",\n\t\tdisabled,\n\t\tsize,\n\t\terror,\n\t\tonClearError,\n\t\tclassName\n\t} = props;\n\n\tassertValidAllowedMime(allowedMime);\n\tassertValidAccept(accept);\n\n\t/** Реф на скрытый нативный input[type=\"file\"] */\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!error\n\t});\n\n\t/** Достигнут ли лимит файлов */\n\tconst isLimitReached = typeof maxFiles === \"number\" && value.length >= maxFiles;\n\n\t/**\n\t * Обработчик выбора файлов из нативного диалога.\n\t * Каждый файл читается через readFile.\n\t * Успешно прочитанные файлы добавляются к текущему массиву value.\n\t */\n\tconst handleChange = useCallback(\n\t\tasync (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst files = e.target.files;\n\t\t\tif (!files || files.length === 0) return;\n\n\t\t\tconst selectedFiles = Array.from(files);\n\n\t\t\t// Сбрасываем значение input чтобы можно было выбрать те же файлы повторно\n\t\t\te.target.value = \"\";\n\n\t\t\t// Сбрасываем ошибку при выборе новых файлов\n\t\t\tif (error && onClearError) onClearError();\n\n\t\t\t// Определяем сколько файлов можно ещё добавить\n\t\t\tconst remaining = typeof maxFiles === \"number\" ? maxFiles - value.length : selectedFiles.length;\n\t\t\tconst filesToProcess = selectedFiles.slice(0, remaining);\n\n\t\t\tif (props.readMode === \"array-buffer\") {\n\t\t\t\t// Читаем файлы как ArrayBuffer и сохраняем точный тип массива для потребителя.\n\t\t\t\tconst results: InputFilesArrayBufferResult[] = [];\n\n\t\t\t\tfor (const file of filesToProcess) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst result = await readFile(file, { allowedMime, maxBytes, mode: \"array-buffer\" });\n\t\t\t\t\t\tresults.push(result);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tif (err instanceof ReadFileError && onReadError) {\n\t\t\t\t\t\t\tonReadError(err);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (results.length > 0) {\n\t\t\t\t\tprops.onChange([...props.value, ...results]);\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Читаем файлы как Data URL и сохраняем точный тип массива для потребителя.\n\t\t\tconst results: InputFilesDataUrlResult[] = [];\n\t\t\tfor (const file of filesToProcess) {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await readFile(file, { allowedMime, maxBytes });\n\t\t\t\t\tresults.push(result);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (err instanceof ReadFileError && onReadError) {\n\t\t\t\t\t\tonReadError(err);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (results.length > 0) {\n\t\t\t\tprops.onChange([...props.value, ...results]);\n\t\t\t}\n\t\t},\n\t\t[props, maxFiles, value.length, allowedMime, maxBytes, onReadError, error, onClearError]\n\t);\n\n\t/** Клик по видимому контролу открывает нативный диалог */\n\tconst handleClick = useCallback(() => {\n\t\tinputRef.current?.click();\n\t}, []);\n\n\tconst filesList =\n\t\tprops.readMode === \"array-buffer\" ? (\n\t\t\t<InputFilesList files={props.value} onChange={props.onChange} />\n\t\t) : (\n\t\t\t<InputFilesList files={props.value} onChange={props.onChange} />\n\t\t);\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={error}\n\t\t\tcontrolId={controlId}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<input\n\t\t\t\tref={inputRef}\n\t\t\t\tid={controlId}\n\t\t\t\ttype=\"file\"\n\t\t\t\taccept={(accept ?? allowedMime)?.join(\",\")}\n\t\t\t\tmultiple\n\t\t\t\tdisabled={disabled || isLimitReached}\n\t\t\t\tclassName={styles.hiddenInput}\n\t\t\t\tonChange={handleChange}\n\t\t\t\ttabIndex={-1}\n\t\t\t/>\n\n\t\t\t<InputControl>\n\t\t\t\t{() => (\n\t\t\t\t\t<div\n\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\ttabIndex={disabled || isLimitReached ? -1 : 0}\n\t\t\t\t\t\tonClick={handleClick}\n\t\t\t\t\t\tonKeyDown={(event) => handleKeyboardActivation(event, handleClick, { disabled: disabled || isLimitReached })}\n\t\t\t\t\t\tclassName={cn(uiStyles.uiInputControl, styles.control, !!error && \"invalid\")}\n\t\t\t\t\t\tdata-disabled={disabled || undefined}\n\t\t\t\t\t\taria-invalid={!!error || undefined}\n\t\t\t\t\t\taria-disabled={disabled || isLimitReached}\n\t\t\t\t\t\taria-labelledby={labelId}\n\t\t\t\t\t\taria-describedby={describedBy}>\n\t\t\t\t\t\t<span className={uiStyles.uiPlaceholder}>{isLimitReached ? `Максимум ${maxFiles} файлов` : placeholder}</span>\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</InputControl>\n\n\t\t\t{/* Список выбранных файлов */}\n\t\t\t{filesList}\n\t\t</InputUI>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;ACaA,SAAgB,EAA6C,EAAE,UAAO,eAAwC;CAC7G,IAAM,IAAe,GACnB,MAAkB;EAClB,EAAS,EAAM,QAAQ,GAAG,MAAM,MAAM,CAAK,CAAC;CAC7C,GACA,CAAC,GAAO,CAAQ,CACjB;CAIA,OAFI,CAAC,KAAS,CAAC,EAAM,SAAe,OAGnC,kBAAC,MAAD;EAAI,WAAW,EAAO;YACpB,EAAM,KAAK,GAAM,MACjB,kBAAC,MAAD;GAAwD,WAAW,EAAO;aAA1E,CACC,kBAAC,QAAD;IAAM,WAAW,EAAO;cAAe,EAAK,KAAK;GAAW,CAAA,GAC5D,kBAAC,UAAD;IACC,MAAK;IACL,WAAW,EAAG,EAAO,cAAc,YAAY;IAC/C,eAAe,EAAa,CAAK;IACjC,cAAY,WAAW,EAAK,KAAK;cACjC,kBAAC,GAAD,CAAQ,CAAA;GACD,CAAA,CACL;KATK,GAAG,EAAK,KAAK,KAAK,GAAG,EAAK,KAAK,cASpC,CACJ;CACE,CAAA;AAEN;;;ACmCA,SAAgB,EAAW,GAAwB;CAClD,IAAM,EACL,UACA,gBACA,WACA,gBACA,aACA,aACA,UACA,gBACA,iBAAc,kBACd,aACA,SACA,UACA,iBACA,iBACG;CAGJ,AADA,EAAuB,CAAW,GAClC,EAAkB,CAAM;CAGxB,IAAM,IAAW,EAAyB,IAAI,GACxC,EAAE,cAAW,YAAS,kBAAe,YAAS,mBAAgB,EAAiB;EACpF,UAAU,KAAiC;EAC3C,gBAAgB,CAAC,CAAC;EAClB,UAAU,CAAC,CAAC;CACb,CAAC,GAGK,IAAiB,OAAO,KAAa,YAAY,EAAM,UAAU,GAOjE,IAAe,EACpB,OAAO,MAA2C;EACjD,IAAM,IAAQ,EAAE,OAAO;EACvB,IAAI,CAAC,KAAS,EAAM,WAAW,GAAG;EAElC,IAAM,IAAgB,MAAM,KAAK,CAAK;EAMtC,AAHA,EAAE,OAAO,QAAQ,IAGb,KAAS,KAAc,EAAa;EAGxC,IAAM,IAAY,OAAO,KAAa,WAAW,IAAW,EAAM,SAAS,EAAc,QACnF,IAAiB,EAAc,MAAM,GAAG,CAAS;EAEvD,IAAI,EAAM,aAAa,gBAAgB;GAEtC,IAAM,IAAyC,CAAC;GAEhD,KAAK,IAAM,KAAQ,GAClB,IAAI;IACH,IAAM,IAAS,MAAM,EAAS,GAAM;KAAE;KAAa;KAAU,MAAM;IAAe,CAAC;IACnF,EAAQ,KAAK,CAAM;GACpB,SAAS,GAAK;IACb,AAAI,aAAe,KAAiB,KACnC,EAAY,CAAG;GAEjB;GAGD,AAAI,EAAQ,SAAS,KACpB,EAAM,SAAS,CAAC,GAAG,EAAM,OAAO,GAAG,CAAO,CAAC;GAG5C;EACD;EAGA,IAAM,IAAqC,CAAC;EAC5C,KAAK,IAAM,KAAQ,GAClB,IAAI;GACH,IAAM,IAAS,MAAM,EAAS,GAAM;IAAE;IAAa;GAAS,CAAC;GAC7D,EAAQ,KAAK,CAAM;EACpB,SAAS,GAAK;GACb,AAAI,aAAe,KAAiB,KACnC,EAAY,CAAG;EAEjB;EAED,AAAI,EAAQ,SAAS,KACpB,EAAM,SAAS,CAAC,GAAG,EAAM,OAAO,GAAG,CAAO,CAAC;CAE7C,GACA;EAAC;EAAO;EAAU,EAAM;EAAQ;EAAa;EAAU;EAAa;EAAO;CAAY,CACxF,GAGM,IAAc,QAAkB;EACrC,EAAS,SAAS,MAAM;CACzB,GAAG,CAAC,CAAC,GAEC,KACL,EAAM,UACL,kBAAC,GAAD;EAAgB,OAAO,EAAM;EAAO,UAAU,EAAM;CAAW,CAAA;CAKjE,OACC,kBAAC,GAAD;EACQ;EACM;EACH;EACC;EACL;EACC;EACI;EACF;EACM;EACN;YAVV;GAWC,kBAAC,SAAD;IACC,KAAK;IACL,IAAI;IACJ,MAAK;IACL,SAAS,KAAU,EAAA,EAAc,KAAK,GAAG;IACzC,UAAA;IACA,UAAU,KAAY;IACtB,WAAW,EAAO;IAClB,UAAU;IACV,UAAU;GACV,CAAA;GAED,kBAAC,GAAD,EAAA,gBAEE,kBAAC,OAAD;IACC,MAAK;IACL,UAAU,KAAY,IAAiB,KAAK;IAC5C,SAAS;IACT,YAAY,MAAU,EAAyB,GAAO,GAAa,EAAE,UAAU,KAAY,EAAe,CAAC;IAC3G,WAAW,EAAG,EAAS,gBAAgB,EAAO,SAAS,CAAC,CAAC,KAAS,SAAS;IAC3E,iBAAe,KAAY,KAAA;IAC3B,gBAAc,CAAC,CAAC,KAAS,KAAA;IACzB,iBAAe,KAAY;IAC3B,mBAAiB;IACjB,oBAAkB;cAClB,kBAAC,QAAD;KAAM,WAAW,EAAS;eAAgB,IAAiB,YAAY,EAAS,WAAW;IAAkB,CAAA;GACzG,CAAA,EAEO,CAAA;GAGb;EACO;;AAEX"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as e } from "./ui.module-BisoTevy.js";
|
|
2
|
-
import { c as t, n, o as r, r as i } from "./Input-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { c as t, n, o as r, r as i } from "./Input-BmjlpA09.js";
|
|
3
|
+
import { useCallback as a, useMemo as o, useRef as s } from "react";
|
|
4
|
+
import { cn as c, handleKeyboardActivation as l } from "@ryuzaki13/react-foundation-lib/utils";
|
|
5
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
6
6
|
import { ReadImageError as f, readImageFile as p } from "@ryuzaki13/react-foundation-lib/file";
|
|
7
7
|
var m = {
|
|
8
8
|
control: "EV-Vji",
|
|
@@ -12,11 +12,11 @@ var m = {
|
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/input-image/InputImage.tsx
|
|
14
14
|
function h({ value: h, onChange: g, onClear: _, onReadError: v, allowedMime: y, maxBytes: b, readMode: x, label: S, description: C, placeholder: w = "Выберите изображение", disabled: T, size: E, error: D, onClearError: O, className: k }) {
|
|
15
|
-
let A =
|
|
15
|
+
let A = s(null), { controlId: j, labelId: M, descriptionId: N, errorId: P, describedBy: F } = t({
|
|
16
16
|
hasLabel: S != null,
|
|
17
17
|
hasDescription: !!C,
|
|
18
18
|
hasError: !!D
|
|
19
|
-
}), I =
|
|
19
|
+
}), I = a((e) => x === "array-buffer" ? p(e, {
|
|
20
20
|
allowedMime: y,
|
|
21
21
|
maxBytes: b,
|
|
22
22
|
mode: "array-buffer"
|
|
@@ -27,7 +27,7 @@ function h({ value: h, onChange: g, onClear: _, onReadError: v, allowedMime: y,
|
|
|
27
27
|
y,
|
|
28
28
|
b,
|
|
29
29
|
x
|
|
30
|
-
]), L =
|
|
30
|
+
]), L = o(() => y && y.length > 0 ? y.join(",") : "image/*", [y]), R = a(async (e) => {
|
|
31
31
|
let t = e.target.files?.[0];
|
|
32
32
|
if (t) {
|
|
33
33
|
e.target.value = "", D && O && O();
|
|
@@ -43,10 +43,10 @@ function h({ value: h, onChange: g, onClear: _, onReadError: v, allowedMime: y,
|
|
|
43
43
|
v,
|
|
44
44
|
D,
|
|
45
45
|
O
|
|
46
|
-
]), z =
|
|
46
|
+
]), z = a(() => {
|
|
47
47
|
A.current?.click();
|
|
48
48
|
}, []);
|
|
49
|
-
return /* @__PURE__ */
|
|
49
|
+
return /* @__PURE__ */ d(r, {
|
|
50
50
|
label: S,
|
|
51
51
|
description: C,
|
|
52
52
|
disabled: T,
|
|
@@ -57,7 +57,7 @@ function h({ value: h, onChange: g, onClear: _, onReadError: v, allowedMime: y,
|
|
|
57
57
|
labelId: M,
|
|
58
58
|
descriptionId: N,
|
|
59
59
|
errorId: P,
|
|
60
|
-
children: [/* @__PURE__ */
|
|
60
|
+
children: [/* @__PURE__ */ u("input", {
|
|
61
61
|
ref: A,
|
|
62
62
|
id: j,
|
|
63
63
|
type: "file",
|
|
@@ -66,27 +66,27 @@ function h({ value: h, onChange: g, onClear: _, onReadError: v, allowedMime: y,
|
|
|
66
66
|
className: m.hiddenInput,
|
|
67
67
|
onChange: R,
|
|
68
68
|
tabIndex: -1
|
|
69
|
-
}), /* @__PURE__ */
|
|
70
|
-
endAdornment: _ ? /* @__PURE__ */
|
|
69
|
+
}), /* @__PURE__ */ u(i, {
|
|
70
|
+
endAdornment: _ ? /* @__PURE__ */ u(n, {
|
|
71
71
|
onClick: _,
|
|
72
72
|
disabled: T
|
|
73
73
|
}) : void 0,
|
|
74
74
|
endAdornmentWidth: _ ? "var(--control-height)" : void 0,
|
|
75
|
-
children: ({ controlClassName: t }) => /* @__PURE__ */
|
|
75
|
+
children: ({ controlClassName: t }) => /* @__PURE__ */ u("div", {
|
|
76
76
|
role: "button",
|
|
77
77
|
tabIndex: T ? -1 : 0,
|
|
78
78
|
onClick: z,
|
|
79
|
-
onKeyDown: (e) =>
|
|
80
|
-
className:
|
|
79
|
+
onKeyDown: (e) => l(e, z, { disabled: T }),
|
|
80
|
+
className: c(e.uiInputControl, m.control, t, !!D && "invalid"),
|
|
81
81
|
"data-disabled": T || void 0,
|
|
82
82
|
"aria-invalid": !!D || void 0,
|
|
83
83
|
"aria-disabled": T,
|
|
84
84
|
"aria-labelledby": M,
|
|
85
85
|
"aria-describedby": F,
|
|
86
|
-
children: h ? /* @__PURE__ */
|
|
86
|
+
children: h ? /* @__PURE__ */ u("span", {
|
|
87
87
|
className: m.fileName,
|
|
88
88
|
children: h.meta.name
|
|
89
|
-
}) : /* @__PURE__ */
|
|
89
|
+
}) : /* @__PURE__ */ u("span", {
|
|
90
90
|
className: e.uiPlaceholder,
|
|
91
91
|
children: w
|
|
92
92
|
})
|
|
@@ -97,4 +97,4 @@ function h({ value: h, onChange: g, onClear: _, onReadError: v, allowedMime: y,
|
|
|
97
97
|
//#endregion
|
|
98
98
|
export { h as t };
|
|
99
99
|
|
|
100
|
-
//# sourceMappingURL=InputImage-
|
|
100
|
+
//# sourceMappingURL=InputImage-Cw8rPYQu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputImage-
|
|
1
|
+
{"version":3,"file":"InputImage-Cw8rPYQu.js","names":[],"sources":["../../src/input-image/InputImage.module.scss","../../src/input-image/InputImage.tsx"],"sourcesContent":[".control {\n\theight: var(--control-height);\n\twidth: 100%;\n\tpadding: 0 var(--space-sm);\n\tfont-size: var(--font-size-md);\n\tcursor: pointer;\n\tdisplay: flex;\n\talign-items: center;\n}\n\n.fileName {\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.hiddenInput {\n\tposition: absolute;\n\twidth: 0;\n\theight: 0;\n\topacity: 0;\n\toverflow: hidden;\n\tpointer-events: none;\n}\n","import { useCallback, useMemo, useRef } from \"react\";\n\nimport { ImageMime, ReadImageError, readImageFile, ReadImageResult, ReadMode } from \"@ryuzaki13/react-foundation-lib/file\";\nimport { cn, handleKeyboardActivation } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { InputClearButton, InputControl, InputUI, useInputFieldIds } from \"../input\";\nimport { UiBaseProps } from \"../types\";\nimport uiStyles from \"../ui.module.scss\";\n\nimport styles from \"./InputImage.module.scss\";\n\n/**\n * Пропсы компонента InputImage.\n *\n * Компонент предназначен для выбора одного изображения.\n * Внешний вид идентичен InputText.\n *\n * Под капотом использует readImageFile, который:\n * - Проверяет что файл является изображением (image/*)\n * - Валидирует MIME-тип по списку allowedMime\n * - В режиме \"data-url\" автоматически извлекает размеры изображения (dimensions)\n */\nexport interface InputImageProps extends UiBaseProps<ReadImageResult, ReadImageResult | undefined> {\n\t/** Callback очистки выбранного изображения. Если передан — отображается кнопка «крестик» */\n\tonClear?: () => void;\n\t/** Callback ошибки чтения (невалидный формат, не изображение, превышение размера и т.д.) */\n\tonReadError?: (error: ReadImageError) => void;\n\n\t/** Допустимые MIME-типы изображений — передаётся в readImageFile */\n\tallowedMime?: readonly ImageMime[];\n\t/** Максимальный размер файла в байтах — передаётся в readImageFile */\n\tmaxBytes?: number;\n\t/** Режим чтения: \"data-url\" (по умолчанию, с извлечением dimensions) или \"array-buffer\" */\n\treadMode?: ReadMode;\n\n\t/** Текст ошибки под полем */\n\terror?: string;\n\t/** Callback сброса ошибки (вызывается при повторном выборе изображения) */\n\tonClearError?: () => void;\n\t/** CSS-класс обёртки */\n\tclassName?: string;\n}\n\n/**\n * InputImage — компонент выбора одного изображения.\n *\n * Визуально идентичен InputText. Под капотом использует readImageFile,\n * который валидирует что файл — изображение и извлекает его размеры.\n *\n * HTML-атрибут accept формируется автоматически из allowedMime\n * или по умолчанию равен \"image/*\".\n */\nexport function InputImage({\n\tvalue,\n\tonChange,\n\tonClear,\n\tonReadError,\n\tallowedMime,\n\tmaxBytes,\n\treadMode,\n\tlabel,\n\tdescription,\n\tplaceholder = \"Выберите изображение\",\n\tdisabled,\n\tsize,\n\terror,\n\tonClearError,\n\tclassName\n}: InputImageProps) {\n\t/** Реф на скрытый нативный input[type=\"file\"] */\n\tconst inputRef = useRef<HTMLInputElement>(null);\n\tconst { controlId, labelId, descriptionId, errorId, describedBy } = useInputFieldIds({\n\t\thasLabel: label !== undefined && label !== null,\n\t\thasDescription: !!description,\n\t\thasError: !!error\n\t});\n\n\tconst readSelectedImage = useCallback(\n\t\t(file: File) => {\n\t\t\tif (readMode === \"array-buffer\") {\n\t\t\t\treturn readImageFile(file, { allowedMime, maxBytes, mode: \"array-buffer\" });\n\t\t\t}\n\n\t\t\treturn readImageFile(file, { allowedMime, maxBytes });\n\t\t},\n\t\t[allowedMime, maxBytes, readMode]\n\t);\n\n\t/**\n\t * Формируем HTML-атрибут accept из allowedMime.\n\t * Если allowedMime не указан — принимаем любые изображения (image/*).\n\t */\n\tconst accept = useMemo(() => {\n\t\tif (allowedMime && allowedMime.length > 0) {\n\t\t\treturn allowedMime.join(\",\");\n\t\t}\n\t\treturn \"image/*\";\n\t}, [allowedMime]);\n\n\t/**\n\t * Обработчик выбора файла из нативного диалога.\n\t * Читает файл через readImageFile и передаёт результат в onChange.\n\t */\n\tconst handleChange = useCallback(\n\t\tasync (e: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst file = e.target.files?.[0];\n\t\t\tif (!file) return;\n\n\t\t\t// Сбрасываем значение input чтобы можно было выбрать тот же файл повторно\n\t\t\te.target.value = \"\";\n\n\t\t\t// Сбрасываем ошибку при повторном выборе\n\t\t\tif (error && onClearError) onClearError();\n\n\t\t\ttry {\n\t\t\t\tconst result = await readSelectedImage(file);\n\t\t\t\tonChange(result);\n\t\t\t} catch (err) {\n\t\t\t\tif (err instanceof ReadImageError && onReadError) {\n\t\t\t\t\tonReadError(err);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[readSelectedImage, onChange, onReadError, error, onClearError]\n\t);\n\n\t/** Клик по видимому контролу открывает нативный диалог */\n\tconst handleClick = useCallback(() => {\n\t\tinputRef.current?.click();\n\t}, []);\n\n\treturn (\n\t\t<InputUI\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\tdisabled={disabled}\n\t\t\tclassName={className}\n\t\t\tsize={size}\n\t\t\terror={error}\n\t\t\tcontrolId={controlId}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}>\n\t\t\t<input\n\t\t\t\tref={inputRef}\n\t\t\t\tid={controlId}\n\t\t\t\ttype=\"file\"\n\t\t\t\taccept={accept}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tclassName={styles.hiddenInput}\n\t\t\t\tonChange={handleChange}\n\t\t\t\ttabIndex={-1}\n\t\t\t/>\n\n\t\t\t{/* Видимый контрол, стилизованный под InputText */}\n\t\t\t<InputControl\n\t\t\t\tendAdornment={onClear ? <InputClearButton onClick={onClear} disabled={disabled} /> : undefined}\n\t\t\t\tendAdornmentWidth={onClear ? \"var(--control-height)\" : undefined}>\n\t\t\t\t{({ controlClassName }) => (\n\t\t\t\t\t<div\n\t\t\t\t\t\trole=\"button\"\n\t\t\t\t\t\ttabIndex={disabled ? -1 : 0}\n\t\t\t\t\t\tonClick={handleClick}\n\t\t\t\t\t\tonKeyDown={(event) => handleKeyboardActivation(event, handleClick, { disabled })}\n\t\t\t\t\t\tclassName={cn(uiStyles.uiInputControl, styles.control, controlClassName, !!error && \"invalid\")}\n\t\t\t\t\t\tdata-disabled={disabled || undefined}\n\t\t\t\t\t\taria-invalid={!!error || undefined}\n\t\t\t\t\t\taria-disabled={disabled}\n\t\t\t\t\t\taria-labelledby={labelId}\n\t\t\t\t\t\taria-describedby={describedBy}>\n\t\t\t\t\t\t{value ? (\n\t\t\t\t\t\t\t<span className={styles.fileName}>{value.meta.name}</span>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<span className={uiStyles.uiPlaceholder}>{placeholder}</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</InputControl>\n\t\t</InputUI>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;ACoDA,SAAgB,EAAW,EAC1B,UACA,aACA,YACA,gBACA,gBACA,aACA,aACA,UACA,gBACA,iBAAc,wBACd,aACA,SACA,UACA,iBACA,gBACmB;CAEnB,IAAM,IAAW,EAAyB,IAAI,GACxC,EAAE,cAAW,YAAS,kBAAe,YAAS,mBAAgB,EAAiB;EACpF,UAAU,KAAiC;EAC3C,gBAAgB,CAAC,CAAC;EAClB,UAAU,CAAC,CAAC;CACb,CAAC,GAEK,IAAoB,GACxB,MACI,MAAa,iBACT,EAAc,GAAM;EAAE;EAAa;EAAU,MAAM;CAAe,CAAC,IAGpE,EAAc,GAAM;EAAE;EAAa;CAAS,CAAC,GAErD;EAAC;EAAa;EAAU;CAAQ,CACjC,GAMM,IAAS,QACV,KAAe,EAAY,SAAS,IAChC,EAAY,KAAK,GAAG,IAErB,WACL,CAAC,CAAW,CAAC,GAMV,IAAe,EACpB,OAAO,MAA2C;EACjD,IAAM,IAAO,EAAE,OAAO,QAAQ;EACzB,OAML;GAHA,EAAE,OAAO,QAAQ,IAGb,KAAS,KAAc,EAAa;GAExC,IAAI;IAEH,EAAS,MADY,EAAkB,CAAI,CAC5B;GAChB,SAAS,GAAK;IACb,AAAI,aAAe,KAAkB,KACpC,EAAY,CAAG;GAEjB;EATwC;CAUzC,GACA;EAAC;EAAmB;EAAU;EAAa;EAAO;CAAY,CAC/D,GAGM,IAAc,QAAkB;EACrC,EAAS,SAAS,MAAM;CACzB,GAAG,CAAC,CAAC;CAEL,OACC,kBAAC,GAAD;EACQ;EACM;EACH;EACC;EACL;EACC;EACI;EACF;EACM;EACN;YAVV,CAWC,kBAAC,SAAD;GACC,KAAK;GACL,IAAI;GACJ,MAAK;GACG;GACE;GACV,WAAW,EAAO;GAClB,UAAU;GACV,UAAU;EACV,CAAA,GAGD,kBAAC,GAAD;GACC,cAAc,IAAU,kBAAC,GAAD;IAAkB,SAAS;IAAmB;GAAW,CAAA,IAAI,KAAA;GACrF,mBAAmB,IAAU,0BAA0B,KAAA;cACrD,EAAE,0BACH,kBAAC,OAAD;IACC,MAAK;IACL,UAAU,IAAW,KAAK;IAC1B,SAAS;IACT,YAAY,MAAU,EAAyB,GAAO,GAAa,EAAE,YAAS,CAAC;IAC/E,WAAW,EAAG,EAAS,gBAAgB,EAAO,SAAS,GAAkB,CAAC,CAAC,KAAS,SAAS;IAC7F,iBAAe,KAAY,KAAA;IAC3B,gBAAc,CAAC,CAAC,KAAS,KAAA;IACzB,iBAAe;IACf,mBAAiB;IACjB,oBAAkB;cACjB,IACA,kBAAC,QAAD;KAAM,WAAW,EAAO;eAAW,EAAM,KAAK;IAAW,CAAA,IAEzD,kBAAC,QAAD;KAAM,WAAW,EAAS;eAAgB;IAAkB,CAAA;GAEzD,CAAA;EAEO,CAAA,CACN;;AAEX"}
|