@ryuzaki13/react-foundation-ui 1.0.1 → 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/index.js +1 -1
- package/dist/badge/stories/Badge.stories.js +22 -22
- package/dist/base-table/index.js +2 -2
- package/dist/button/index.js +7 -7
- package/dist/button/stories/Button.stories.js +1 -1
- package/dist/check-box/index.js +1 -1
- package/dist/check-box/stories/CheckBox.stories.js +25 -25
- package/dist/chunks/{BadgeList-6qL9oNAp.js → BadgeList-DYgun2rf.js} +16 -16
- package/dist/chunks/{BadgeList-6qL9oNAp.js.map → BadgeList-DYgun2rf.js.map} +1 -1
- 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-DjeTJkTT.js +435 -0
- package/dist/chunks/{CalendarView-DjShdvRD.js.map → CalendarView-DjeTJkTT.js.map} +1 -1
- package/dist/chunks/CheckBox-BowNqqd3.js +48 -0
- package/dist/chunks/{CheckBox-CulnjNvJ.js.map → CheckBox-BowNqqd3.js.map} +1 -1
- package/dist/chunks/{DateInput-LSSvObtg.js → DateInput--tfofQ2x.js} +68 -68
- package/dist/chunks/{DateInput-LSSvObtg.js.map → DateInput--tfofQ2x.js.map} +1 -1
- 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-BPS4BeWZ.js.map → Dialog-CFIvGxER.js.map} +1 -1
- package/dist/chunks/DisclosureGroup-CfRTkl6Z.js +49 -0
- package/dist/chunks/{DisclosureGroup-Plk2M_Vl.js.map → DisclosureGroup-CfRTkl6Z.js.map} +1 -1
- package/dist/chunks/{DropZone-DPGTpHI6.js → DropZone-kJfbZU5g.js} +22 -22
- package/dist/chunks/{DropZone-DPGTpHI6.js.map → DropZone-kJfbZU5g.js.map} +1 -1
- package/dist/chunks/{DropdownMenu-Ds-trH4M.js → DropdownMenu-DQeR3y7M.js} +138 -138
- package/dist/chunks/{DropdownMenu-Ds-trH4M.js.map → DropdownMenu-DQeR3y7M.js.map} +1 -1
- 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/Input-BmjlpA09.js +227 -0
- package/dist/chunks/{Input-Wrew1puH.js.map → Input-BmjlpA09.js.map} +1 -1
- package/dist/chunks/{InputDateTime-2PCX8an8.js → InputDateTime-CxfAFe2L.js} +56 -56
- package/dist/chunks/{InputDateTime-2PCX8an8.js.map → InputDateTime-CxfAFe2L.js.map} +1 -1
- package/dist/chunks/{InputFile-Ca-bRo93.js → InputFile-CyZu__B_.js} +17 -17
- package/dist/chunks/{InputFile-Ca-bRo93.js.map → InputFile-CyZu__B_.js.map} +1 -1
- package/dist/chunks/{InputFiles-pI9rQXOI.js → InputFiles-CrTJV27R.js} +31 -31
- package/dist/chunks/{InputFiles-pI9rQXOI.js.map → InputFiles-CrTJV27R.js.map} +1 -1
- package/dist/chunks/{InputImage-B522AQzl.js → InputImage-Cw8rPYQu.js} +18 -18
- package/dist/chunks/{InputImage-B522AQzl.js.map → InputImage-Cw8rPYQu.js.map} +1 -1
- package/dist/chunks/{LabeledExpandableActionPanel-CWmOSWeS.js → LabeledExpandableActionPanel-D3kUvmFH.js} +26 -26
- package/dist/chunks/{LabeledExpandableActionPanel-CWmOSWeS.js.map → LabeledExpandableActionPanel-D3kUvmFH.js.map} +1 -1
- package/dist/chunks/Listbox-BZlp5qHz.js +81 -0
- package/dist/chunks/{Listbox-B6F_IKQv.js.map → Listbox-BZlp5qHz.js.map} +1 -1
- package/dist/chunks/{MultiSelect-CUXA8gx-.js → MultiSelect-D1XYuwH1.js} +113 -113
- package/dist/chunks/{MultiSelect-CUXA8gx-.js.map → MultiSelect-D1XYuwH1.js.map} +1 -1
- package/dist/chunks/{NotificationsHost-Bnq7xFKO.js → NotificationsHost-_icJx4xR.js} +44 -44
- package/dist/chunks/{NotificationsHost-Bnq7xFKO.js.map → NotificationsHost-_icJx4xR.js.map} +1 -1
- package/dist/chunks/{PresetRangeDateInput-B_8jsilZ.js → PresetRangeDateInput-CapirptQ.js} +11 -11
- package/dist/chunks/{PresetRangeDateInput-B_8jsilZ.js.map → PresetRangeDateInput-CapirptQ.js.map} +1 -1
- package/dist/chunks/RadioButton-D0uA0rX_.js +48 -0
- package/dist/chunks/{RadioButton-D5vPW4Yr.js.map → RadioButton-D0uA0rX_.js.map} +1 -1
- 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-CoAYWNOn.js → Select-CXeVjVKA.js} +11 -11
- package/dist/chunks/{Select-CoAYWNOn.js.map → Select-CXeVjVKA.js.map} +1 -1
- package/dist/chunks/{SerializableSelect-awBOWKTj.js → SerializableSelect-DkYeJtAO.js} +2 -2
- package/dist/chunks/{SerializableSelect-awBOWKTj.js.map → SerializableSelect-DkYeJtAO.js.map} +1 -1
- package/dist/chunks/{SingleDateTimeInput-o44Vlwdk.js → SingleDateTimeInput-BmeuVGQT.js} +78 -78
- package/dist/chunks/{SingleDateTimeInput-o44Vlwdk.js.map → SingleDateTimeInput-BmeuVGQT.js.map} +1 -1
- 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-abZq176J.js.map → StateSelect-1jH3uLz9.js.map} +1 -1
- package/dist/chunks/{Switch-DHMnZVmN.js → Switch-B57Qmy1z.js} +19 -19
- package/dist/chunks/{Switch-DHMnZVmN.js.map → Switch-B57Qmy1z.js.map} +1 -1
- package/dist/chunks/{TextEditorLexicalClient-Dt4eaPA3.js → TextEditorLexicalClient-DRhAswpP.js} +204 -204
- package/dist/chunks/{TextEditorLexicalClient-Dt4eaPA3.js.map → TextEditorLexicalClient-DRhAswpP.js.map} +1 -1
- package/dist/chunks/{Textarea-DOVrPH4I.js → Textarea-C9UdUueF.js} +2 -2
- package/dist/chunks/{Textarea-DOVrPH4I.js.map → Textarea-C9UdUueF.js.map} +1 -1
- package/dist/chunks/{TimePanel-_kF2RtHk.js → TimePanel-b4saqoUY.js} +27 -27
- package/dist/chunks/{TimePanel-_kF2RtHk.js.map → TimePanel-b4saqoUY.js.map} +1 -1
- 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-C76RYavo.js → TreeMultiSelect-CfQhlfnC.js} +6 -6
- package/dist/chunks/{TreeMultiSelect-C76RYavo.js.map → TreeMultiSelect-CfQhlfnC.js.map} +1 -1
- package/dist/chunks/{TreePickerBase-qNHIWbYL.js → TreePickerBase-BBUOWsSu.js} +49 -49
- package/dist/chunks/{TreePickerBase-qNHIWbYL.js.map → TreePickerBase-BBUOWsSu.js.map} +1 -1
- package/dist/chunks/{TreeSelect-LEhNdPCX.js → TreeSelect-2wUXs90E.js} +6 -6
- package/dist/chunks/{TreeSelect-LEhNdPCX.js.map → TreeSelect-2wUXs90E.js.map} +1 -1
- package/dist/chunks/base-table-CoQlKABk.js +514 -0
- package/dist/chunks/{base-table-ij2guVMB.js.map → base-table-CoQlKABk.js.map} +1 -1
- 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-CzZ8Xzkk.js → layout-picker-MWaImn3L.js} +34 -34
- package/dist/chunks/{layout-picker-CzZ8Xzkk.js.map → layout-picker-MWaImn3L.js.map} +1 -1
- package/dist/chunks/{misc-Bj0y3ERC.js → misc-DoqZBMof.js} +110 -110
- package/dist/chunks/{misc-Bj0y3ERC.js.map → misc-DoqZBMof.js.map} +1 -1
- package/dist/chunks/{modal-B4ivQb2h.js → modal-B3HY3laL.js} +40 -40
- package/dist/chunks/{modal-B4ivQb2h.js.map → modal-B3HY3laL.js.map} +1 -1
- package/dist/chunks/multi-select-BzYIviCU.js +1305 -0
- package/dist/chunks/multi-select-BzYIviCU.js.map +1 -0
- package/dist/chunks/{picker-gIUs0nE_.js → picker-Dg55Ss-B.js} +74 -74
- package/dist/chunks/{picker-gIUs0nE_.js.map → picker-Dg55Ss-B.js.map} +1 -1
- package/dist/chunks/{popover-C79P5bm2.js → popover-xJJqy1v6.js} +52 -52
- package/dist/chunks/{popover-C79P5bm2.js.map → popover-xJJqy1v6.js.map} +1 -1
- 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-CigVo4Ju.js → slider-CFKsfxFp.js} +83 -83
- package/dist/chunks/{slider-CigVo4Ju.js.map → slider-CFKsfxFp.js.map} +1 -1
- package/dist/chunks/sortable-DcTIAbjD.js +185 -0
- package/dist/chunks/{sortable-BZqnZ_LA.js.map → sortable-DcTIAbjD.js.map} +1 -1
- package/dist/chunks/{table-CK-CM2zD.js → table-Dc3AqMzP.js} +21 -21
- package/dist/chunks/{table-CK-CM2zD.js.map → table-Dc3AqMzP.js.map} +1 -1
- 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-D5ikIIng.js → tabs-DlnVVMJl.js} +96 -96
- package/dist/chunks/{tabs-D5ikIIng.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/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/stories/DateInput.stories.js +2 -2
- 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/stories/SingleDateTimeInput.stories.js +38 -38
- package/dist/date-time-input/stories/TimePanel.stories.js +9 -9
- package/dist/detail/index.js +1 -1
- package/dist/detail/stories/Detail.stories.js +1 -1
- package/dist/dialog/index.js +1 -1
- package/dist/dialog/stories/Dialog.stories.js +16 -16
- package/dist/disclosure/index.js +1 -1
- package/dist/disclosure/stories/Disclosure.stories.js +1 -1
- package/dist/drop-zone/index.js +1 -1
- package/dist/drop-zone/stories/DropZone.stories.js +14 -14
- package/dist/errors/index.js +47 -47
- 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/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/index.js +1 -1
- package/dist/input-file/stories/InputFile.stories.js +9 -9
- package/dist/input-files/index.js +1 -1
- package/dist/input-files/stories/InputFiles.stories.js +9 -9
- package/dist/input-image/index.js +1 -1
- package/dist/input-image/stories/InputImage.stories.js +15 -15
- 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/list/index.js +27 -27
- package/dist/listbox/index.js +1 -1
- package/dist/listbox/stories/Listbox.stories.js +19 -19
- package/dist/misc/index.js +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 -1141
- package/dist/multi-select/ui/stories/MultiSelect.stories.js +17 -17
- package/dist/notifications/index.js +1 -1
- package/dist/notifications/ui/stories/NotificationsHost.stories.js +59 -59
- package/dist/period-select/index.js +20 -20
- package/dist/period-select/stories/PeriodSelect.stories.js +17 -17
- package/dist/picker/index.js +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/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/index.js +2 -2
- package/dist/select/stories/Select.stories.js +23 -23
- package/dist/select/stories/SerializableSelect.stories.js +22 -22
- package/dist/separator/index.js +1 -1
- package/dist/simple-table/index.js +5 -5
- 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/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.js +23 -23
- package/dist/styles.css +1 -1
- package/dist/switch/index.js +1 -1
- package/dist/switch/stories/Switch.stories.js +11 -11
- package/dist/table/index.js +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.js +39 -39
- package/dist/text/index.js +20 -20
- 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/index.js +2 -2
- package/dist/tree-select/stories/TreeMultiSelect.stories.js +9 -9
- package/dist/tree-select/stories/TreeSelect.stories.js +9 -9
- package/dist/tree-table/index.js +32 -32
- package/dist/wheel-picker/index.js +1 -1
- package/package.json +11 -1
- package/dist/chunks/CalendarView-DjShdvRD.js +0 -435
- package/dist/chunks/CheckBox-CulnjNvJ.js +0 -48
- package/dist/chunks/Detail-DKolHye4.js +0 -80
- package/dist/chunks/DisclosureGroup-Plk2M_Vl.js +0 -49
- package/dist/chunks/Input-Wrew1puH.js +0 -227
- package/dist/chunks/Listbox-B6F_IKQv.js +0 -81
- package/dist/chunks/RadioButton-D5vPW4Yr.js +0 -48
- package/dist/chunks/RadioGroup-BAhN1d1X.js +0 -121
- package/dist/chunks/StateSelect-abZq176J.js +0 -78
- package/dist/chunks/base-table-ij2guVMB.js +0 -514
- package/dist/chunks/sortable-BZqnZ_LA.js +0 -185
- package/dist/input-search/index.js.map +0 -1
- package/dist/multi-select/index.js.map +0 -1
|
@@ -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 {
|
|
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,42 +16,42 @@ 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
53
|
let r = typeof S == "number" ? S - _.length : n.length, i = n.slice(0, r);
|
|
54
|
-
if (
|
|
54
|
+
if (c.readMode === "array-buffer") {
|
|
55
55
|
let e = [];
|
|
56
56
|
for (let t of i) try {
|
|
57
57
|
let n = await m(t, {
|
|
@@ -63,7 +63,7 @@ function _(o) {
|
|
|
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
69
|
let a = [];
|
|
@@ -76,9 +76,9 @@ function _(o) {
|
|
|
76
76
|
} catch (e) {
|
|
77
77
|
e instanceof d && v && v(e);
|
|
78
78
|
}
|
|
79
|
-
a.length > 0 &&
|
|
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 _(o) {
|
|
|
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 _(o) {
|
|
|
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 _(o) {
|
|
|
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 _(o) {
|
|
|
138
138
|
//#endregion
|
|
139
139
|
export { g as n, _ as t };
|
|
140
140
|
|
|
141
|
-
//# sourceMappingURL=InputFiles-
|
|
141
|
+
//# sourceMappingURL=InputFiles-CrTJV27R.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputFiles-pI9rQXOI.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":"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"}
|
|
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":"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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, 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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t } from "./
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { t as e } from "./Button-CCWuggdA.js";
|
|
2
|
+
import { l as t } from "./misc-DoqZBMof.js";
|
|
3
|
+
import { useCallback as n, useId as r, useState as i } from "react";
|
|
4
|
+
import { cn as a } from "@ryuzaki13/react-foundation-lib/utils";
|
|
5
|
+
import { ChevronsLeftIcon as o, ChevronsRightIcon as s } from "lucide-react";
|
|
6
|
+
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
7
7
|
var u = {
|
|
8
8
|
expandableActionPanel: "sj-rIq",
|
|
9
9
|
content: "_3anR7j",
|
|
@@ -15,21 +15,21 @@ var u = {
|
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/expandable-action-panel/ExpandableActionPanel.tsx
|
|
17
17
|
function d({ children: d, className: f, contentClassName: p, toggleClassName: m, open: h, defaultOpen: g = !1, disabled: _, onOpenChange: v, expandLabel: y = "Раскрыть панель действий влево", collapseLabel: b = "Свернуть панель действий", panelLabel: x = "Действия панели", itemSelector: S, scrollPadding: C, smoothScroll: w }) {
|
|
18
|
-
let [T, E] =
|
|
18
|
+
let [T, E] = i(g), D = r(), O = h !== void 0, k = O ? h : T, A = n((e) => {
|
|
19
19
|
let t = typeof e == "function" ? e(k) : e;
|
|
20
20
|
O || E(t), v?.(t);
|
|
21
21
|
}, [
|
|
22
22
|
O,
|
|
23
23
|
v,
|
|
24
24
|
k
|
|
25
|
-
]), j = () => A((e) => !e), M = k ?
|
|
26
|
-
return /* @__PURE__ */
|
|
27
|
-
className:
|
|
25
|
+
]), j = () => A((e) => !e), M = k ? s : o;
|
|
26
|
+
return /* @__PURE__ */ l("div", {
|
|
27
|
+
className: a(u.expandableActionPanel, f),
|
|
28
28
|
"data-ui": "expandable-action-panel",
|
|
29
29
|
"data-open": k ? "" : void 0,
|
|
30
|
-
children: [/* @__PURE__ */
|
|
30
|
+
children: [/* @__PURE__ */ c(e, {
|
|
31
31
|
className: m,
|
|
32
|
-
icon: /* @__PURE__ */
|
|
32
|
+
icon: /* @__PURE__ */ c(M, {}),
|
|
33
33
|
title: k ? b : y,
|
|
34
34
|
disabled: _,
|
|
35
35
|
variant: "neutralOutline",
|
|
@@ -38,12 +38,12 @@ function d({ children: d, className: f, contentClassName: p, toggleClassName: m,
|
|
|
38
38
|
"data-ui": "expandable-action-panel-toggle",
|
|
39
39
|
"data-action": k ? "collapse-action-panel" : "expand-action-panel",
|
|
40
40
|
onClick: j
|
|
41
|
-
}), k && /* @__PURE__ */
|
|
41
|
+
}), k && /* @__PURE__ */ c("div", {
|
|
42
42
|
id: D,
|
|
43
43
|
role: "group",
|
|
44
44
|
"aria-label": x,
|
|
45
|
-
className:
|
|
46
|
-
children: /* @__PURE__ */
|
|
45
|
+
className: a(u.content, p),
|
|
46
|
+
children: /* @__PURE__ */ c(t, {
|
|
47
47
|
className: u.contentScroller,
|
|
48
48
|
itemSelector: S,
|
|
49
49
|
scrollPadding: C,
|
|
@@ -55,28 +55,28 @@ function d({ children: d, className: f, contentClassName: p, toggleClassName: m,
|
|
|
55
55
|
}
|
|
56
56
|
//#endregion
|
|
57
57
|
//#region src/expandable-action-panel/LabeledExpandableActionPanel.tsx
|
|
58
|
-
function f({ label: e, className: t, labelClassName:
|
|
58
|
+
function f({ label: e, className: t, labelClassName: n, labelStyle: r, labelMinWidth: i = "12em", panelClassName: o, open: s, defaultOpen: f, ...p }) {
|
|
59
59
|
let m = {
|
|
60
|
-
...
|
|
61
|
-
minWidth:
|
|
60
|
+
...r,
|
|
61
|
+
minWidth: i
|
|
62
62
|
}, h = typeof e == "string" ? e : void 0;
|
|
63
|
-
return /* @__PURE__ */
|
|
64
|
-
className:
|
|
63
|
+
return /* @__PURE__ */ l("div", {
|
|
64
|
+
className: a(u.labeledPanel, t),
|
|
65
65
|
"data-ui": "labeled-expandable-action-panel",
|
|
66
|
-
children: [/* @__PURE__ */
|
|
67
|
-
className:
|
|
66
|
+
children: [/* @__PURE__ */ c("div", {
|
|
67
|
+
className: a("flexEllipsis", u.label, n),
|
|
68
68
|
style: m,
|
|
69
69
|
title: h,
|
|
70
70
|
children: e
|
|
71
|
-
}), /* @__PURE__ */
|
|
71
|
+
}), /* @__PURE__ */ c(d, {
|
|
72
72
|
...p,
|
|
73
|
-
open:
|
|
73
|
+
open: s,
|
|
74
74
|
defaultOpen: f,
|
|
75
|
-
className:
|
|
75
|
+
className: a(u.labeledActionPanel, o)
|
|
76
76
|
})]
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
//#endregion
|
|
80
80
|
export { d as n, f as t };
|
|
81
81
|
|
|
82
|
-
//# sourceMappingURL=LabeledExpandableActionPanel-
|
|
82
|
+
//# sourceMappingURL=LabeledExpandableActionPanel-D3kUvmFH.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LabeledExpandableActionPanel-
|
|
1
|
+
{"version":3,"file":"LabeledExpandableActionPanel-D3kUvmFH.js","names":[],"sources":["../../src/expandable-action-panel/ExpandableActionPanel.module.scss","../../src/expandable-action-panel/ExpandableActionPanel.tsx","../../src/expandable-action-panel/LabeledExpandableActionPanel.tsx"],"sourcesContent":[".expandableActionPanel {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: flex-end;\n\tgap: var(--space-sm);\n\tmin-width: var(--control-height);\n\tmax-width: 100%;\n\toverflow: hidden;\n}\n\n.content {\n\tmin-width: 0;\n\tmax-width: 100%;\n\tflex: 1 1 auto;\n\toverflow: hidden;\n}\n\n.contentScroller {\n\twidth: 100%;\n\tmin-width: 0;\n}\n\n.labeledPanel {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: var(--space-sm);\n\twidth: 100%;\n\tmin-width: 0;\n}\n\n.label {\n\tcolor: var(--content-0);\n}\n\n.labeledActionPanel {\n\tflex: 0 1 auto;\n}\n","import React, { PropsWithChildren, useCallback, useId, useState } from \"react\";\n\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\nimport { ChevronsLeftIcon, ChevronsRightIcon } from \"lucide-react\";\n\nimport { Button } from \"../button\";\nimport { OneStepScroller } from \"../misc\";\n\nimport styles from \"./ExpandableActionPanel.module.scss\";\n\nexport interface ExpandableActionPanelProps extends PropsWithChildren {\n\tclassName?: string;\n\tcontentClassName?: string;\n\ttoggleClassName?: string;\n\topen?: boolean;\n\tdefaultOpen?: boolean;\n\tdisabled?: boolean;\n\tonOpenChange?: (open: boolean) => void;\n\texpandLabel?: string;\n\tcollapseLabel?: string;\n\tpanelLabel?: string;\n\titemSelector?: string;\n\tscrollPadding?: number;\n\tsmoothScroll?: boolean;\n}\n\n/**\n * Горизонтальная раскрывающаяся панель действий.\n * Не знает о внешнем layout и может использоваться рядом с любым содержимым.\n */\nexport function ExpandableActionPanel({\n\tchildren,\n\tclassName,\n\tcontentClassName,\n\ttoggleClassName,\n\topen: controlledOpen,\n\tdefaultOpen = false,\n\tdisabled,\n\tonOpenChange,\n\texpandLabel = \"Раскрыть панель действий влево\",\n\tcollapseLabel = \"Свернуть панель действий\",\n\tpanelLabel = \"Действия панели\",\n\titemSelector,\n\tscrollPadding,\n\tsmoothScroll\n}: ExpandableActionPanelProps) {\n\tconst [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);\n\tconst panelId = useId();\n\tconst isControlled = controlledOpen !== undefined;\n\tconst open = isControlled ? controlledOpen : uncontrolledOpen;\n\n\tconst setOpen = useCallback<React.Dispatch<React.SetStateAction<boolean>>>(\n\t\t(value) => {\n\t\t\tconst nextOpen = typeof value === \"function\" ? value(open) : value;\n\n\t\t\tif (!isControlled) {\n\t\t\t\tsetUncontrolledOpen(nextOpen);\n\t\t\t}\n\n\t\t\tonOpenChange?.(nextOpen);\n\t\t},\n\t\t[isControlled, onOpenChange, open]\n\t);\n\n\tconst handleToggle = () => setOpen((prevOpen) => !prevOpen);\n\tconst ToggleIcon = open ? ChevronsRightIcon : ChevronsLeftIcon;\n\n\treturn (\n\t\t<div className={cn(styles.expandableActionPanel, className)} data-ui=\"expandable-action-panel\" data-open={open ? \"\" : undefined}>\n\t\t\t<Button\n\t\t\t\tclassName={toggleClassName}\n\t\t\t\ticon={<ToggleIcon />}\n\t\t\t\ttitle={open ? collapseLabel : expandLabel}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tvariant=\"neutralOutline\"\n\t\t\t\taria-expanded={open}\n\t\t\t\taria-controls={panelId}\n\t\t\t\tdata-ui=\"expandable-action-panel-toggle\"\n\t\t\t\tdata-action={open ? \"collapse-action-panel\" : \"expand-action-panel\"}\n\t\t\t\tonClick={handleToggle}\n\t\t\t/>\n\n\t\t\t{open && (\n\t\t\t\t<div id={panelId} role=\"group\" aria-label={panelLabel} className={cn(styles.content, contentClassName)}>\n\t\t\t\t\t<OneStepScroller\n\t\t\t\t\t\tclassName={styles.contentScroller}\n\t\t\t\t\t\titemSelector={itemSelector}\n\t\t\t\t\t\tscrollPadding={scrollPadding}\n\t\t\t\t\t\tsmooth={smoothScroll}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</OneStepScroller>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n}\n","import React from \"react\";\n\nimport { cn } from \"@ryuzaki13/react-foundation-lib/utils\";\n\nimport { ExpandableActionPanel, ExpandableActionPanelProps } from \"./ExpandableActionPanel\";\nimport styles from \"./ExpandableActionPanel.module.scss\";\n\nexport interface LabeledExpandableActionPanelProps extends Omit<ExpandableActionPanelProps, \"className\"> {\n\tlabel: React.ReactNode;\n\tclassName?: string;\n\tlabelClassName?: string;\n\tlabelStyle?: React.CSSProperties;\n\tlabelMinWidth?: React.CSSProperties[\"minWidth\"];\n\tpanelClassName?: string;\n}\n\n/**\n * Раскрывающаяся панель действий с левым текстом, который сжимается через `flexEllipsis`.\n */\nexport function LabeledExpandableActionPanel({\n\tlabel,\n\tclassName,\n\tlabelClassName,\n\tlabelStyle,\n\tlabelMinWidth = \"12em\",\n\tpanelClassName,\n\topen,\n\tdefaultOpen,\n\t...panelProps\n}: LabeledExpandableActionPanelProps) {\n\tconst resolvedLabelStyle: React.CSSProperties = {\n\t\t...labelStyle,\n\t\tminWidth: labelMinWidth\n\t};\n\tconst title = typeof label === \"string\" ? label : undefined;\n\n\treturn (\n\t\t<div className={cn(styles.labeledPanel, className)} data-ui=\"labeled-expandable-action-panel\">\n\t\t\t<div className={cn(\"flexEllipsis\", styles.label, labelClassName)} style={resolvedLabelStyle} title={title}>\n\t\t\t\t{label}\n\t\t\t</div>\n\t\t\t<ExpandableActionPanel\n\t\t\t\t{...panelProps}\n\t\t\t\topen={open}\n\t\t\t\tdefaultOpen={defaultOpen}\n\t\t\t\tclassName={cn(styles.labeledActionPanel, panelClassName)}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AC8BA,SAAgB,EAAsB,EACrC,aACA,cACA,qBACA,oBACA,MAAM,GACN,iBAAc,IACd,aACA,iBACA,iBAAc,kCACd,mBAAgB,4BAChB,gBAAa,mBACb,iBACA,kBACA,mBAC8B;CAC9B,IAAM,CAAC,GAAkB,KAAuB,EAAS,CAAW,GAC9D,IAAU,EAAM,GAChB,IAAe,MAAmB,KAAA,GAClC,IAAO,IAAe,IAAiB,GAEvC,IAAU,GACd,MAAU;EACV,IAAM,IAAW,OAAO,KAAU,aAAa,EAAM,CAAI,IAAI;EAM7D,AAJK,KACJ,EAAoB,CAAQ,GAG7B,IAAe,CAAQ;CACxB,GACA;EAAC;EAAc;EAAc;CAAI,CAClC,GAEM,UAAqB,GAAS,MAAa,CAAC,CAAQ,GACpD,IAAa,IAAO,IAAoB;CAE9C,OACC,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,uBAAuB,CAAS;EAAG,WAAQ;EAA0B,aAAW,IAAO,KAAK,KAAA;YAAtH,CACC,kBAAC,GAAD;GACC,WAAW;GACX,MAAM,kBAAC,GAAD,CAAa,CAAA;GACnB,OAAO,IAAO,IAAgB;GACpB;GACV,SAAQ;GACR,iBAAe;GACf,iBAAe;GACf,WAAQ;GACR,eAAa,IAAO,0BAA0B;GAC9C,SAAS;EACT,CAAA,GAEA,KACA,kBAAC,OAAD;GAAK,IAAI;GAAS,MAAK;GAAQ,cAAY;GAAY,WAAW,EAAG,EAAO,SAAS,CAAgB;aACpG,kBAAC,GAAD;IACC,WAAW,EAAO;IACJ;IACC;IACf,QAAQ;IACP;GACe,CAAA;EACb,CAAA,CAEF;;AAEP;;;AC5EA,SAAgB,EAA6B,EAC5C,UACA,cACA,mBACA,eACA,mBAAgB,QAChB,mBACA,SACA,gBACA,GAAG,KACkC;CACrC,IAAM,IAA0C;EAC/C,GAAG;EACH,UAAU;CACX,GACM,IAAQ,OAAO,KAAU,WAAW,IAAQ,KAAA;CAElD,OACC,kBAAC,OAAD;EAAK,WAAW,EAAG,EAAO,cAAc,CAAS;EAAG,WAAQ;YAA5D,CACC,kBAAC,OAAD;GAAK,WAAW,EAAG,gBAAgB,EAAO,OAAO,CAAc;GAAG,OAAO;GAA2B;aAClG;EACG,CAAA,GACL,kBAAC,GAAD;GACC,GAAI;GACE;GACO;GACb,WAAW,EAAG,EAAO,oBAAoB,CAAc;EACvD,CAAA,CACG;;AAEP"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { t as e } from "./ui.module-BisoTevy.js";
|
|
2
|
+
import { useEffect as t, useId as n, useLayoutEffect as r, useMemo as i, useRef as a, useState as o } from "react";
|
|
3
|
+
import { cn as s, findFirstEnabledIndex as c, findLastEnabledIndex as l, findNextEnabledIndex as u, handleKeyboardActivation as d } from "@ryuzaki13/react-foundation-lib/utils";
|
|
4
|
+
import { CheckIcon as f } from "lucide-react";
|
|
5
|
+
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
6
|
+
//#region src/listbox/Listbox.tsx
|
|
7
|
+
var h = (e) => e.disabled === !0;
|
|
8
|
+
function g(e, t, n) {
|
|
9
|
+
if (n) {
|
|
10
|
+
if (Array.isArray(t) && t.length > 0) {
|
|
11
|
+
let n = e.findIndex((e) => t.includes(e.value) && !e.disabled);
|
|
12
|
+
if (n >= 0) return n;
|
|
13
|
+
}
|
|
14
|
+
return c(e, h);
|
|
15
|
+
}
|
|
16
|
+
if (t !== void 0) {
|
|
17
|
+
let n = e.findIndex((e) => e.value === t && !e.disabled);
|
|
18
|
+
if (n >= 0) return n;
|
|
19
|
+
}
|
|
20
|
+
return c(e, h);
|
|
21
|
+
}
|
|
22
|
+
function _(_) {
|
|
23
|
+
let { value: v, defaultValue: y, multiple: b, focusOnMount: x, renderItem: S, getKey: C, options: w, onChange: T, id: E, ...D } = _, O = v !== void 0, k = n(), A = E ?? `${k}-listbox`, [j, M] = o(y), N = a(null), [P, F] = o(() => g(w, v ?? y, b)), I = i(() => (O ? v : j) ?? (b ? [] : null), [
|
|
24
|
+
j,
|
|
25
|
+
O,
|
|
26
|
+
b,
|
|
27
|
+
v
|
|
28
|
+
]), L = P, R = (e) => {
|
|
29
|
+
if (e.disabled) return;
|
|
30
|
+
let t;
|
|
31
|
+
if (_.multiple) {
|
|
32
|
+
let n = Array.isArray(I) ? I : [];
|
|
33
|
+
t = n.includes(e.value) ? n.filter((t) => t !== e.value) : [...n, e.value], _.onChange?.(t, e);
|
|
34
|
+
} else t = e.value, _.onChange?.(t, e);
|
|
35
|
+
O || M(t);
|
|
36
|
+
};
|
|
37
|
+
return t(() => {
|
|
38
|
+
let e = N.current?.querySelectorAll("[role=\"option\"]")[L];
|
|
39
|
+
e && e.scrollIntoView({ block: "nearest" });
|
|
40
|
+
}, [L]), r(() => {
|
|
41
|
+
x && N.current?.focus();
|
|
42
|
+
}, [x]), /* @__PURE__ */ p("ul", {
|
|
43
|
+
ref: N,
|
|
44
|
+
id: A,
|
|
45
|
+
role: "listbox",
|
|
46
|
+
"aria-multiselectable": b || void 0,
|
|
47
|
+
"aria-activedescendant": L >= 0 ? `${A}-option-${L}` : void 0,
|
|
48
|
+
tabIndex: 0,
|
|
49
|
+
onKeyDown: (e) => {
|
|
50
|
+
if (e.key === "ArrowDown") e.preventDefault(), F((e) => u(w, e, 1, h));
|
|
51
|
+
else if (e.key === "ArrowUp") e.preventDefault(), F((e) => u(w, e, -1, h));
|
|
52
|
+
else if (e.key === "Home") e.preventDefault(), F(c(w, h));
|
|
53
|
+
else if (e.key === "End") e.preventDefault(), F(l(w, h));
|
|
54
|
+
else if (d(e, () => {
|
|
55
|
+
let e = w[L];
|
|
56
|
+
e && R(e);
|
|
57
|
+
})) return;
|
|
58
|
+
},
|
|
59
|
+
...D,
|
|
60
|
+
className: s(e.uiPanel, "scrollable"),
|
|
61
|
+
children: w.map((t, n) => {
|
|
62
|
+
let r = b ? Array.isArray(I) && I.includes(t.value) : I === t.value, i = n === L;
|
|
63
|
+
return /* @__PURE__ */ m("li", {
|
|
64
|
+
id: `${A}-option-${n}`,
|
|
65
|
+
role: "option",
|
|
66
|
+
"aria-selected": r,
|
|
67
|
+
"aria-disabled": t.disabled || void 0,
|
|
68
|
+
onMouseDown: (e) => {
|
|
69
|
+
e.preventDefault(), !t.disabled && (F(n), R(t));
|
|
70
|
+
},
|
|
71
|
+
tabIndex: -1,
|
|
72
|
+
className: s(e.uiPopupOption, t.disabled && e.disabled, i && e.uiPopupOptionActive, r && e.selected),
|
|
73
|
+
children: [p(r ? f : "span", { className: e.uiPopupOptionIcon }), /* @__PURE__ */ p("div", { children: S ? S(t, r, i) : t.label ?? String(t.value) })]
|
|
74
|
+
}, C ? C(t, n) : n);
|
|
75
|
+
})
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { _ as t };
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=Listbox-BZlp5qHz.js.map
|