@ryuzaki13/react-foundation-ui 1.8.6 → 1.8.8

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.
Files changed (313) hide show
  1. package/dist/advanced-search/index.js +2 -2
  2. package/dist/base-table/index.js +1 -1
  3. package/dist/chunks/{base-table-CYbtifH0.js → base-table-CdcVMDGY.js} +2 -2
  4. package/dist/chunks/{base-table-CYbtifH0.js.map → base-table-CdcVMDGY.js.map} +1 -1
  5. package/dist/chunks/{context-menu-L4KM0FRD.js → context-menu-CE_wfxct.js} +2 -2
  6. package/dist/chunks/{context-menu-L4KM0FRD.js.map → context-menu-CE_wfxct.js.map} +1 -1
  7. package/dist/chunks/date-input-g6l1iDmf.js.map +1 -1
  8. package/dist/chunks/{multi-select-CCgoTHWI.js → multi-select-CHZhWoq6.js} +2 -2
  9. package/dist/chunks/{multi-select-CCgoTHWI.js.map → multi-select-CHZhWoq6.js.map} +1 -1
  10. package/dist/chunks/{picker-Cb3D2Hts.js → picker-BcB3rSQt.js} +2 -2
  11. package/dist/chunks/picker-BcB3rSQt.js.map +1 -0
  12. package/dist/chunks/{select-Baek-IUe.js → select-BorNxjrG.js} +2 -2
  13. package/dist/chunks/{select-Baek-IUe.js.map → select-BorNxjrG.js.map} +1 -1
  14. package/dist/chunks/{table-CrQiurtA.js → table-DcABGh_F.js} +2 -2
  15. package/dist/chunks/{table-CrQiurtA.js.map → table-DcABGh_F.js.map} +1 -1
  16. package/dist/context-menu/index.js +1 -1
  17. package/dist/layout-picker/index.js +1 -1
  18. package/dist/listbox/index.js +1 -1
  19. package/dist/multi-select/index.js +1 -1
  20. package/dist/picker/index.js +1 -1
  21. package/dist/preset-select/index.js +1 -1
  22. package/dist/select/index.js +1 -1
  23. package/dist/simple-table/index.js +1 -1
  24. package/dist/slider/index.js +1 -1
  25. package/dist/state-select/index.js +1 -1
  26. package/dist/styles.css +1 -1
  27. package/dist/table/index.js +1 -1
  28. package/dist/table-sorting/index.js +1 -1
  29. package/dist/tree-select/index.js +1 -1
  30. package/dist/tree-table/index.js +1 -1
  31. package/package.json +4 -4
  32. package/storybook-static/assets/{Badge-CV8uR5lW.js → Badge-CxQIV1VM.js} +1 -1
  33. package/storybook-static/assets/{Badge.stories-DqTFDEB6.js → Badge.stories-BJkImUYK.js} +1 -1
  34. package/storybook-static/assets/{BadgeList-CVWvhSS7.js → BadgeList-DCcUez-d.js} +1 -1
  35. package/storybook-static/assets/{Button-C5Z6nJ9s.js → Button-BM_JnsIi.js} +1 -1
  36. package/storybook-static/assets/{Button-DtySOeyD.js → Button-Dh35R_JE.js} +1 -1
  37. package/storybook-static/assets/{Button.stories--Wr67DaY.js → Button.stories-BsgEwN-G.js} +1 -1
  38. package/storybook-static/assets/{CalendarView-ZzqQ8UIe.js → CalendarView-Bu5aaqrw.js} +1 -1
  39. package/storybook-static/assets/{CheckBox-BfNP6vO6.js → CheckBox-B93BCdtW.js} +1 -1
  40. package/storybook-static/assets/{CheckBox-BBNTe4u8.js → CheckBox-DB_H7Jkd.js} +1 -1
  41. package/storybook-static/assets/{CheckBox.module-CoYygdZx.js → CheckBox.module-BOAVN-Ny.js} +1 -1
  42. package/storybook-static/assets/{CheckBox.stories-B4Sv2TXp.js → CheckBox.stories-ChtE7IN-.js} +1 -1
  43. package/storybook-static/assets/{Color-6AOWCN3U-Ce5w8Y2l.js → Color-6AOWCN3U-CuY1qZ6d.js} +1 -1
  44. package/storybook-static/assets/{ContextMenu-Boi0R7-s.js → ContextMenu-B30yur26.js} +1 -1
  45. package/storybook-static/assets/{ContextMenu-D-lV53Zc.js → ContextMenu-DeoYEX8n.js} +1 -1
  46. package/storybook-static/assets/{ContextMenu.stories-D_rxDbLk.js → ContextMenu.stories-B80uu025.js} +1 -1
  47. package/storybook-static/assets/{CustomOptionButton-VYfjUfhW.js → CustomOptionButton-DQp71AHJ.js} +1 -1
  48. package/storybook-static/assets/{DateInput-f-RcBdOb.js → DateInput-CMhHGS-s.js} +1 -1
  49. package/storybook-static/assets/{DateInput-q2hPsJcH.js → DateInput-wIlcdKHD.js} +1 -1
  50. package/storybook-static/assets/{DateInput.stories-zQzjIsfx.js → DateInput.stories-DS45syC3.js} +1 -1
  51. package/storybook-static/assets/{DateRangePresetSelect-DQBOF8f5.js → DateRangePresetSelect-31S_37_9.js} +1 -1
  52. package/storybook-static/assets/{DateRangePresetSelect-Ciikik1_.js → DateRangePresetSelect-DgpOHDW1.js} +1 -1
  53. package/storybook-static/assets/{DateRangePresetSelect.stories-BF8IP5Ep.js → DateRangePresetSelect.stories-3VlGka98.js} +1 -1
  54. package/storybook-static/assets/{Detail-CEl8URNQ.js → Detail-CxFnUUkK.js} +1 -1
  55. package/storybook-static/assets/{Detail.stories-Mr3ypLAA.js → Detail.stories-DqgQuwn1.js} +1 -1
  56. package/storybook-static/assets/{Dialog-Dj2y3EO1.js → Dialog-B0VCykP7.js} +1 -1
  57. package/storybook-static/assets/{Dialog-BydPFV17.js → Dialog-CdJK__QW.js} +1 -1
  58. package/storybook-static/assets/{Dialog.stories-C1WlZdyp.js → Dialog.stories-C1ABO4hq.js} +1 -1
  59. package/storybook-static/assets/{Disclosure-DH77E5hY.js → Disclosure-g89eWjtw.js} +1 -1
  60. package/storybook-static/assets/{Disclosure.stories-B9ZVczUX.js → Disclosure.stories-B2CCl9Dg.js} +1 -1
  61. package/storybook-static/assets/{DisclosureGroup-CIoFeosY.js → DisclosureGroup-DZ-1k-kK.js} +1 -1
  62. package/storybook-static/assets/{DocsRenderer-JROSPFPF-CbJN3X6f.js → DocsRenderer-JROSPFPF-C54xfLi3.js} +2 -2
  63. package/storybook-static/assets/{DropZone-DTBV-X-J.js → DropZone-CpVX5FJc.js} +1 -1
  64. package/storybook-static/assets/{DropZone-CR7xRn_b.js → DropZone-FboQPtkt.js} +1 -1
  65. package/storybook-static/assets/{DropZone.stories-Cw_og1Cs.js → DropZone.stories-Dtt5tKix.js} +1 -1
  66. package/storybook-static/assets/{DropdownMenu-CVIeHT8N.js → DropdownMenu--_ifmQMt.js} +1 -1
  67. package/storybook-static/assets/{ExpandableActionPanel-D8U6v8X7.js → ExpandableActionPanel-B2g9YRDI.js} +1 -1
  68. package/storybook-static/assets/{ExpandableActionPanel.stories-D42CZyOc.js → ExpandableActionPanel.stories-DnhAdkcl.js} +1 -1
  69. package/storybook-static/assets/{Flex-Bcsl0U5O.js → Flex-B-x1Ohkp.js} +1 -1
  70. package/storybook-static/assets/{Flex.stories-C0vSa3mh.js → Flex.stories-BYEkhW_Q.js} +1 -1
  71. package/storybook-static/assets/{FlexContainer-LmZIdhq2.js → FlexContainer-BWyPlTMB.js} +1 -1
  72. package/storybook-static/assets/{FlexItem-vkDYa5tA.js → FlexItem-pu3E11Sf.js} +1 -1
  73. package/storybook-static/assets/{FloatingPopover-DvU3oc_q.js → FloatingPopover-DOyMIo2-.js} +1 -1
  74. package/storybook-static/assets/FormattedTableCell-Cja58sq0.js +15 -0
  75. package/storybook-static/assets/{Grid-BCzygAqy.js → Grid-CzO0Ae1r.js} +1 -1
  76. package/storybook-static/assets/{Grid-Wl0Y0YAh.js → Grid-DDQ5Q1Zu.js} +1 -1
  77. package/storybook-static/assets/{Grid.stories-G6gMmKCP.js → Grid.stories-Bh-o6XTQ.js} +1 -1
  78. package/storybook-static/assets/{GridContainer-qDguE1HS.js → GridContainer-fKYgDsLl.js} +1 -1
  79. package/storybook-static/assets/{ImageCropper.stories-u6rOvDbd.js → ImageCropper.stories-Dy2RiAcH.js} +3 -3
  80. package/storybook-static/assets/{ImageRenderer-BYIRHN5G.js → ImageRenderer-qllJTZXD.js} +1 -1
  81. package/storybook-static/assets/{ImageRenderer.stories-BMEHEIVH.js → ImageRenderer.stories-DvE7n1QW.js} +1 -1
  82. package/storybook-static/assets/{ImageView.stories-DiEA93Yz.js → ImageView.stories-BmxCb-j1.js} +1 -1
  83. package/storybook-static/assets/{ImageViewer.stories-DyxctGxM.js → ImageViewer.stories-7cW5swP8.js} +2 -2
  84. package/storybook-static/assets/{ImageViewerRuntime--h_3C2s0.js → ImageViewerRuntime-CZu7J7wR.js} +2 -2
  85. package/storybook-static/assets/{Input-B2kOwWOU.js → Input-DWC0iHTm.js} +1 -1
  86. package/storybook-static/assets/{Input-CViRQ_rj.js → Input-JgKfpyoY.js} +1 -1
  87. package/storybook-static/assets/{Input.stories-D9eo9MWc.js → Input.stories-D_3AMqSf.js} +1 -1
  88. package/storybook-static/assets/{InputDateTime-T9_iyG4G.js → InputDateTime-DZOKr9oV.js} +1 -1
  89. package/storybook-static/assets/{InputDateTime.stories-DzegljaN.js → InputDateTime.stories-CFVXMtGS.js} +1 -1
  90. package/storybook-static/assets/{InputFile-CA3YpXnm.js → InputFile-BM_2v8Vr.js} +1 -1
  91. package/storybook-static/assets/{InputFile-Cvdj6RfC.js → InputFile-QkBKG4MF.js} +1 -1
  92. package/storybook-static/assets/{InputFile.stories-C18UaXPS.js → InputFile.stories-y_bqA0ji.js} +1 -1
  93. package/storybook-static/assets/{InputFiles-nS_qsXY7.js → InputFiles-0MQlpVXZ.js} +1 -1
  94. package/storybook-static/assets/{InputFiles-C4OkTG9M.js → InputFiles-CPMaf-0m.js} +1 -1
  95. package/storybook-static/assets/{InputFiles.stories-BYd0Pe0R.js → InputFiles.stories-FvkbnEu9.js} +1 -1
  96. package/storybook-static/assets/{InputFilesList-CXPf7Ui_.js → InputFilesList-LSKKFWI2.js} +1 -1
  97. package/storybook-static/assets/{InputImage-kd50L1Gf.js → InputImage-BtWMRvPj.js} +1 -1
  98. package/storybook-static/assets/{InputImage-jDVIxP7S.js → InputImage-CtHvsmW2.js} +1 -1
  99. package/storybook-static/assets/{InputImage.stories-D-xmS4Qj.js → InputImage.stories-DB4Dpqrp.js} +1 -1
  100. package/storybook-static/assets/{InteractiveComponents-D13nzSK7.js → InteractiveComponents-TycCPNdw.js} +1 -1
  101. package/storybook-static/assets/{InteractiveComponents.stories-yITzDh-Y.js → InteractiveComponents.stories-BPL6ph-t.js} +1 -1
  102. package/storybook-static/assets/{LayoutPicker-BfYXGIKb.js → LayoutPicker-121F1oKo.js} +1 -1
  103. package/storybook-static/assets/{LayoutPicker-9FVo0bF3.js → LayoutPicker-amQe8EyF.js} +1 -1
  104. package/storybook-static/assets/{LayoutPicker.stories-B-UnuGFM.js → LayoutPicker.stories-DpcjEEH4.js} +1 -1
  105. package/storybook-static/assets/{Listbox-9LVlsDzw.js → Listbox-D-Sqd9jb.js} +1 -1
  106. package/storybook-static/assets/{Listbox-C53-i-L6.js → Listbox-P5hFPYDA.js} +1 -1
  107. package/storybook-static/assets/{Listbox.stories-CCN72ABE.js → Listbox.stories-CL85ceLu.js} +1 -1
  108. package/storybook-static/assets/{Modal-CoXpuByh.js → Modal-Cn7uJut0.js} +1 -1
  109. package/storybook-static/assets/{Modal.stories-DAj_oPSt.js → Modal.stories-DgRduIwP.js} +1 -1
  110. package/storybook-static/assets/{ModalManagerProvider-C7pGT0B3.js → ModalManagerProvider-BpTBqDR5.js} +1 -1
  111. package/storybook-static/assets/{MultiSelect-DZ2krz-D.js → MultiSelect-BAHGljvC.js} +1 -1
  112. package/storybook-static/assets/{MultiSelect-DqeGNK15.js → MultiSelect-Bdq-guyW.js} +1 -1
  113. package/storybook-static/assets/{MultiSelect.stories-BoVHXMbn.js → MultiSelect.stories-6C-TQL1s.js} +1 -1
  114. package/storybook-static/assets/{NoData-N6Pbu0LD.js → NoData-mxG4mL4e.js} +1 -1
  115. package/storybook-static/assets/{NotificationsHost--uPz1G3j.js → NotificationsHost-CygepfX-.js} +1 -1
  116. package/storybook-static/assets/{NotificationsHost.stories-B-X-Ljxs.js → NotificationsHost.stories-B7ZmvjI6.js} +1 -1
  117. package/storybook-static/assets/{ODataMultiSelect-7U6nJdqB.js → ODataMultiSelect-BHl4B00F.js} +1 -1
  118. package/storybook-static/assets/{ODataMultiSelect.stories-B-t6MsOr.js → ODataMultiSelect.stories-BHSj5rjf.js} +1 -1
  119. package/storybook-static/assets/{ODataSelect-Dy-fSgE6.js → ODataSelect-foaFaP6d.js} +1 -1
  120. package/storybook-static/assets/{ODataSelect.stories-DhqHtcmD.js → ODataSelect.stories-82q9oBl6.js} +1 -1
  121. package/storybook-static/assets/{ODataTreeMultiSelect-Ol0nuytU.js → ODataTreeMultiSelect-CyFx96Sj.js} +1 -1
  122. package/storybook-static/assets/{ODataTreeMultiSelect.stories-BupVzhbY.js → ODataTreeMultiSelect.stories-zLBWRIRi.js} +1 -1
  123. package/storybook-static/assets/{ODataTreeSelect-EkpDmDyk.js → ODataTreeSelect-DyPqYfQa.js} +1 -1
  124. package/storybook-static/assets/{ODataTreeSelect.stories-CFdbwyEg.js → ODataTreeSelect.stories-BSowZVpd.js} +1 -1
  125. package/storybook-static/assets/{OneStepScroller-rmyPl9f5.js → OneStepScroller-B_7N8BYz.js} +1 -1
  126. package/storybook-static/assets/Option-CVAAv8AB.css +1 -0
  127. package/storybook-static/assets/{Option-72PrSDkj.js → Option-DvXrygAo.js} +1 -1
  128. package/storybook-static/assets/{OptionButton-Br8QoJL7.js → OptionButton-CaiIhG8s.js} +1 -1
  129. package/storybook-static/assets/{PeriodSelect-DEZVGWGR.js → PeriodSelect-CcheHEx9.js} +1 -1
  130. package/storybook-static/assets/{PeriodSelect-C5Xk-g4Y.js → PeriodSelect-DQWcrf3z.js} +1 -1
  131. package/storybook-static/assets/{PeriodSelect.stories-BVBP97HW.js → PeriodSelect.stories-BoZAwgxD.js} +1 -1
  132. package/storybook-static/assets/{PickerTriggerActions-DSmRHX1I.js → PickerTriggerActions-C7iwI6po.js} +1 -1
  133. package/storybook-static/assets/{Popover-BpbeIq6-.js → Popover-BA61XeKS.js} +1 -1
  134. package/storybook-static/assets/{Popover-1KQwBxEJ.js → Popover-DemWjUAR.js} +1 -1
  135. package/storybook-static/assets/{Popover.stories-6RDZ0TND.js → Popover.stories-BZtYXuDy.js} +1 -1
  136. package/storybook-static/assets/{PresetRangeDateInput-BdkKzY69.js → PresetRangeDateInput-BPRlqmwn.js} +1 -1
  137. package/storybook-static/assets/{PresetRangeDateInput-CDhgmyFs.js → PresetRangeDateInput-QZD02nll.js} +1 -1
  138. package/storybook-static/assets/{PresetRangeDateInput.stories-BoE41IUK.js → PresetRangeDateInput.stories-fqhQho_t.js} +1 -1
  139. package/storybook-static/assets/{PresetSelect-CA5AyOOy.js → PresetSelect-604ElKuM.js} +1 -1
  140. package/storybook-static/assets/README-BSfoRcmy.js +648 -0
  141. package/storybook-static/assets/README-B_PcyrCy.js +876 -0
  142. package/storybook-static/assets/README-Bbmv2xJo.js +860 -0
  143. package/storybook-static/assets/README-C1ki7lL7.js +417 -0
  144. package/storybook-static/assets/README-CFCpUZA-.js +1093 -0
  145. package/storybook-static/assets/README-CMoAGNQ5.js +282 -0
  146. package/storybook-static/assets/README-CN_Y4pYZ.js +273 -0
  147. package/storybook-static/assets/README-COR9RMzk.js +1487 -0
  148. package/storybook-static/assets/README-CRfJujEw.js +1309 -0
  149. package/storybook-static/assets/README-CZ49-EeH.js +347 -0
  150. package/storybook-static/assets/README-D01AizPk.js +288 -0
  151. package/storybook-static/assets/README-DL6uUTPo.js +694 -0
  152. package/storybook-static/assets/README-DSHEoxUa.js +334 -0
  153. package/storybook-static/assets/README-Q-znYcgF.js +338 -0
  154. package/storybook-static/assets/README-qNwFrtLd.js +420 -0
  155. package/storybook-static/assets/{RadioButton-IDzSzftl.js → RadioButton-CbD6ZIHI.js} +1 -1
  156. package/storybook-static/assets/{RadioButton-DCoo55ld.js → RadioButton-DndugDg6.js} +1 -1
  157. package/storybook-static/assets/{RadioButton.stories-BEk1uc2x.js → RadioButton.stories-DLBVXRhH.js} +1 -1
  158. package/storybook-static/assets/{RadioGroup-VSiqFUI1.js → RadioGroup-CtB8u1R5.js} +1 -1
  159. package/storybook-static/assets/{RadioGroup-CbBmuFtC.js → RadioGroup-Cvgo5T_8.js} +1 -1
  160. package/storybook-static/assets/{RadioGroup.stories-DR7Vskyy.js → RadioGroup.stories-L1ZkFYiC.js} +1 -1
  161. package/storybook-static/assets/{Scrollable-CDZ18AWy.js → Scrollable-CGvhxTPd.js} +1 -1
  162. package/storybook-static/assets/{Select-IWQpo0LQ.js → Select-ByBilOog.js} +1 -1
  163. package/storybook-static/assets/{Select-YjugVUKX.js → Select-D4MdId1m.js} +1 -1
  164. package/storybook-static/assets/{Select.stories-4JpnXfaB.js → Select.stories-Dt-IM20Z.js} +1 -1
  165. package/storybook-static/assets/{SerializableSelect-oxnbV26a.js → SerializableSelect-nkDX-4xv.js} +1 -1
  166. package/storybook-static/assets/{SerializableSelect.stories-CjVcuU4t.js → SerializableSelect.stories-BWozK3v0.js} +1 -1
  167. package/storybook-static/assets/{SingleDateTimeInput-DFPke7bv.js → SingleDateTimeInput-BM3iEHnL.js} +1 -1
  168. package/storybook-static/assets/{SingleDateTimeInput-CQ1_ABKA.js → SingleDateTimeInput-DwIACH7q.js} +1 -1
  169. package/storybook-static/assets/{SingleDateTimeInput.stories--Nky_yBh.js → SingleDateTimeInput.stories-GluT9Gra.js} +1 -1
  170. package/storybook-static/assets/{Slider-DGVl0dbV.js → Slider-Cijr3rDj.js} +1 -1
  171. package/storybook-static/assets/{Slider-L7pqW7xG.js → Slider-DZF2K2Ew.js} +1 -1
  172. package/storybook-static/assets/{Slider.stories-DkqUavTk.js → Slider.stories-CKkDEud8.js} +1 -1
  173. package/storybook-static/assets/{SliderInput-B7U8M2UN.js → SliderInput-BpmhOQah.js} +1 -1
  174. package/storybook-static/assets/{SliderInput-Dn5-Dt4w.js → SliderInput-D_DduGKi.js} +1 -1
  175. package/storybook-static/assets/{SliderInput.stories-B9WBQOiA.js → SliderInput.stories-vb6qkP3q.js} +1 -1
  176. package/storybook-static/assets/{Sortable-DxdXjG1a.js → Sortable-CbhgYqYI.js} +1 -1
  177. package/storybook-static/assets/{Sortable.stories-D1rp2l9M.js → Sortable.stories-BGYwnEIs.js} +1 -1
  178. package/storybook-static/assets/{Splitter-yZpkev96.js → Splitter-CIrkYu0w.js} +1 -1
  179. package/storybook-static/assets/{Splitter.stories-C3TCKNhu.js → Splitter.stories-BiWcwOKt.js} +1 -1
  180. package/storybook-static/assets/{StateSelect-CaAFL9Jr.js → StateSelect-PvcnwH-_.js} +1 -1
  181. package/storybook-static/assets/{StateSelect-DZjPblfU.js → StateSelect-ZSH1VqJo.js} +1 -1
  182. package/storybook-static/assets/{StateSelect.stories-D7EwT0sO.js → StateSelect.stories-XIHGksRX.js} +1 -1
  183. package/storybook-static/assets/{StringToggle.stories-DuaWy2LK.js → StringToggle.stories-ZIPWDjST.js} +1 -1
  184. package/storybook-static/assets/{Switch-C0GQ2oXw.js → Switch-Bf1TvVDU.js} +1 -1
  185. package/storybook-static/assets/{Switch-DCNQT47U.js → Switch-DHkppwyI.js} +1 -1
  186. package/storybook-static/assets/{Switch.stories-CAIEfQb6.js → Switch.stories-DflM2SkS.js} +1 -1
  187. package/storybook-static/assets/{Table-Be1uta4G.js → Table-CzJkgWa8.js} +1 -1
  188. package/storybook-static/assets/Table.stories-BaalIcC1.js +207 -0
  189. package/storybook-static/assets/{Tabs-Co7Z92UK.js → Tabs-Cys2Volu.js} +1 -1
  190. package/storybook-static/assets/{Tabs.stories-D84U8aJM.js → Tabs.stories-D_fVcYeD.js} +2 -2
  191. package/storybook-static/assets/{TabsBox-CUpOXGdh.js → TabsBox-B9W9qy2m.js} +1 -1
  192. package/storybook-static/assets/{TagInput-BbLK6uxZ.js → TagInput-CnPuhz64.js} +1 -1
  193. package/storybook-static/assets/{TagInput.stories-D34JCfyM.js → TagInput.stories-CU9IW-n_.js} +1 -1
  194. package/storybook-static/assets/{Text-DtJw3wMU.js → Text-CellD6Ua.js} +1 -1
  195. package/storybook-static/assets/{Textarea-C9MWeqLC.js → Textarea-BIne8oBO.js} +1 -1
  196. package/storybook-static/assets/{Textarea-Cz6RWJdh.js → Textarea-CNJiLJKb.js} +1 -1
  197. package/storybook-static/assets/{Textarea.stories-DqK16XGS.js → Textarea.stories-BfgWsqEp.js} +1 -1
  198. package/storybook-static/assets/{TimePanel-DcZ-UUgO.js → TimePanel-BY8XyZeb.js} +1 -1
  199. package/storybook-static/assets/{TimePanel.stories-BafOmX3I.js → TimePanel.stories-BEqFKJd3.js} +1 -1
  200. package/storybook-static/assets/{Toggle-oYTkCbEJ.js → Toggle-CTmUXxr_.js} +1 -1
  201. package/storybook-static/assets/{Toggle-CgU6o7qM.js → Toggle-Dyiyi7DV.js} +1 -1
  202. package/storybook-static/assets/{Toggle.stories-CbmOBWIu.js → Toggle.stories-DysLQdUc.js} +1 -1
  203. package/storybook-static/assets/{TreeMultiSelect-B4WfXc4Z.js → TreeMultiSelect-CDOGzEjr.js} +1 -1
  204. package/storybook-static/assets/{TreeMultiSelect-DN_CYg-F.js → TreeMultiSelect-DUQQUlTr.js} +1 -1
  205. package/storybook-static/assets/{TreeMultiSelect.stories-DYVj6Rm6.js → TreeMultiSelect.stories-Ca1Ezfej.js} +1 -1
  206. package/storybook-static/assets/{TreePickerBase-8gA_hIXn.js → TreePickerBase-CHdoSW2m.js} +1 -1
  207. package/storybook-static/assets/{TreeSelect-2bjYl5ox.js → TreeSelect-DBpqAEoz.js} +1 -1
  208. package/storybook-static/assets/{TreeSelect-CTtmHF-B.js → TreeSelect-DvmeQO0H.js} +1 -1
  209. package/storybook-static/assets/{TreeSelect.stories-BEAY61pJ.js → TreeSelect.stories-zRpBXhMU.js} +1 -1
  210. package/storybook-static/assets/{TreeTable-B4BaHybr.js → TreeTable-Dpr1hsTN.js} +1 -1
  211. package/storybook-static/assets/{TreeTable.stories-lLwH2Gzl.js → TreeTable.stories-D4mBQSif.js} +2 -2
  212. package/storybook-static/assets/{WithTooltip-7X4HQR7L-Cakt_JaX.js → WithTooltip-7X4HQR7L-DQ4Qthn2.js} +1 -1
  213. package/storybook-static/assets/{array-D-_yMMUK-CIRmlF93.js → array-D-_yMMUK-BQ0uu1hZ.js} +1 -1
  214. package/storybook-static/assets/{async-DFALSYBD.js → async-phnLSjcK.js} +1 -1
  215. package/storybook-static/assets/axe-_9eNhXQJ.js +20 -0
  216. package/storybook-static/assets/{blocks-Dr191OF5.js → blocks-Dx5UE11l.js} +6 -6
  217. package/storybook-static/assets/check-Bn8-yPh2.js +1 -0
  218. package/storybook-static/assets/chevron-down-BZ9pvYFr.js +1 -0
  219. package/storybook-static/assets/chevron-left-DWqaY-om.js +1 -0
  220. package/storybook-static/assets/chevron-right-NPmcbCK0.js +1 -0
  221. package/storybook-static/assets/{chunk-242VQQM5-BMWWiybC.js → chunk-242VQQM5-bHL6qIJq.js} +1 -1
  222. package/storybook-static/assets/{chunk-DRQKCCAG-CqE-Zrl9.js → chunk-DRQKCCAG-DvsmU7ha.js} +1 -1
  223. package/storybook-static/assets/{chunk-IMSF75WX-yvVUwIQZ.js → chunk-IMSF75WX-CGYlPTyG.js} +1 -1
  224. package/storybook-static/assets/{chunk-KJHJLCBK-D-yQfkOi.js → chunk-KJHJLCBK-yRlRMfNs.js} +1 -1
  225. package/storybook-static/assets/{chunk-QQBDHPVZ-B98qboss.js → chunk-QQBDHPVZ-DC5n6Pix.js} +1 -1
  226. package/storybook-static/assets/{chunk-W22LQPXL-BR_vFDlt.js → chunk-W22LQPXL-BYQdtiug.js} +1 -1
  227. package/storybook-static/assets/{circle-alert-Is-jAV5H.js → circle-alert-CJwtzjGy.js} +1 -1
  228. package/storybook-static/assets/circle-check-DwTtGRlB.js +1 -0
  229. package/storybook-static/assets/{components-DqFIc_sf.js → components-Cs2kpiik.js} +12 -12
  230. package/storybook-static/assets/{contextMenu-CWKJO78E.js → contextMenu-B5c0sszu.js} +1 -1
  231. package/storybook-static/assets/{createControlledStoryRender-DHsyXc1B.js → createControlledStoryRender-BouhvX-R.js} +1 -1
  232. package/storybook-static/assets/{date-segments-D3HouZ37.js → date-segments-DeoMkKv9.js} +1 -1
  233. package/storybook-static/assets/{defaultRenderers-V5HI39JH.js → defaultRenderers-BHXboKuy.js} +1 -1
  234. package/storybook-static/assets/{dom-B3G_GtJw.js → dom-DBd_DWF8.js} +1 -1
  235. package/storybook-static/assets/{download-B61X2hm8.js → download-r-5pPKGQ.js} +1 -1
  236. package/storybook-static/assets/{error-BZrNlEUO.js → error-De9R4E_F.js} +1 -1
  237. package/storybook-static/assets/{file-vPGnhPr-.js → file-CwRoWxeB.js} +1 -1
  238. package/storybook-static/assets/floating-ui.react-69N16zFe.js +1 -0
  239. package/storybook-static/assets/formatter-L2YTDE3Q-CRGuSxAF.js +1 -0
  240. package/storybook-static/assets/{formatters-CBgrBeSA-DY6OIAc8.js → formatters-CBgrBeSA-CqB1pZxS.js} +1 -1
  241. package/storybook-static/assets/{foundationLib-10USAmEi.js → foundationLib-BIHXPLOP.js} +1 -1
  242. package/storybook-static/assets/{hooks-C8GJ9Cvf.js → hooks-DC_oxxhF.js} +2 -2
  243. package/storybook-static/assets/{iframe-Bu7ux79g.js → iframe-C5-IVaAZ.js} +23 -23
  244. package/storybook-static/assets/iframe-CKeBtmwl.js +1 -0
  245. package/storybook-static/assets/{info-CnuHFdaB.js → info-CNW3iwvW.js} +1 -1
  246. package/storybook-static/assets/{matchers-JIUQ3HVY-DvR2XErZ.js → matchers-JIUQ3HVY-C789_MAK.js} +1 -1
  247. package/storybook-static/assets/{media-BycWpjAl.js → media-D9cE2tzi.js} +1 -1
  248. package/storybook-static/assets/odata-CGxTTNvg.js +1 -0
  249. package/storybook-static/assets/{odata-service-B6TxBSLm-BW9QLSrS.js → odata-service-B6TxBSLm-Bq8Ya67E.js} +1 -1
  250. package/storybook-static/assets/{odataFetchFn-CAzdQ6ar.js → odataFetchFn-BS9TBmIl.js} +1 -1
  251. package/storybook-static/assets/{odataStoryFixtures-CX6euJaD.js → odataStoryFixtures-C83OxXaj.js} +2 -2
  252. package/storybook-static/assets/{persisted-BKBboERB.js → persisted-BPpV66dG.js} +1 -1
  253. package/storybook-static/assets/{preload-helper-BHmFeTtP.js → preload-helper-wdlQj8DP.js} +1 -1
  254. package/storybook-static/assets/react-18-D4o7zN8K.js +9 -0
  255. package/storybook-static/assets/react-B0_DoKoo.js +9 -0
  256. package/storybook-static/assets/{react-C21x__mS.js → react-BZJXY1be.js} +1 -1
  257. package/storybook-static/assets/{react-qN2cStNd.js → react-Bl2r1tuC.js} +1 -1
  258. package/storybook-static/assets/{react-CvkUhHUq.js → react-GkniIHEK.js} +1 -1
  259. package/storybook-static/assets/{react-dom-2o2phaJG.js → react-dom-BzEl8usk.js} +1 -1
  260. package/storybook-static/assets/{refresh-cw-ByNiehPJ.js → refresh-cw-BIVSqnGe.js} +1 -1
  261. package/storybook-static/assets/{rolldown-runtime-C0FnF6B9.js → rolldown-runtime-DkW27tQK.js} +1 -1
  262. package/storybook-static/assets/{settings-2-BGG8WBgX.js → settings-2-9-qrKLUO.js} +1 -1
  263. package/storybook-static/assets/{shim-BUMlC1GG.js → shim-DlYORV19.js} +1 -1
  264. package/storybook-static/assets/{sortable-6C6S-hq-.js → sortable-BTkW6ZiT.js} +1 -1
  265. package/storybook-static/assets/syntaxhighlighter-QEQV7K2Y-Ch82sVZk.js +6 -0
  266. package/storybook-static/assets/{theming-mTWhffkp.js → theming-Cvtrnj7n.js} +1 -1
  267. package/storybook-static/assets/{trash-2-EYPGQg68.js → trash-2-D4oKWLBp.js} +1 -1
  268. package/storybook-static/assets/{treeStoryFixtures-Ci7STpiz.js → treeStoryFixtures-DXHh9GL3.js} +1 -1
  269. package/storybook-static/assets/{triangle-alert-qcSLqRkW.js → triangle-alert-CBOrIa31.js} +1 -1
  270. package/storybook-static/assets/{ui.module-D4CuGr8r.js → ui.module-Cat84Nza.js} +1 -1
  271. package/storybook-static/assets/{uiClasses-CVGbL980.js → uiClasses-B9c6dZuu.js} +1 -1
  272. package/storybook-static/assets/{useFlexClasses-Gn9spXEB.js → useFlexClasses-SgVG37Bb.js} +1 -1
  273. package/storybook-static/assets/{useODataSelectBase-LQU24QnI.js → useODataSelectBase-B6fc-K7G.js} +1 -1
  274. package/storybook-static/assets/{useODataTreeData-0I485gNf.js → useODataTreeData-BEHsAQxw.js} +1 -1
  275. package/storybook-static/assets/usePickerDefaultFilter-5Q1pAV4d.js +1 -0
  276. package/storybook-static/assets/{usePickerQuery-B0a5nSeM.js → usePickerQuery-B-2MddV7.js} +1 -1
  277. package/storybook-static/assets/{usePickerTriggerController-DMRm063p.js → usePickerTriggerController-CyBsILzT.js} +1 -1
  278. package/storybook-static/assets/{utils-DUM89eIj.js → utils-tg3ibbzi.js} +1 -1
  279. package/storybook-static/assets/x-BZ_zKXO5.js +1 -0
  280. package/storybook-static/iframe.html +7 -7
  281. package/storybook-static/index.json +1 -1
  282. package/storybook-static/project.json +1 -1
  283. package/storybook-static/sb-addons/chromatic-com-storybook-1/manager-bundle.js +35 -33
  284. package/storybook-static/sb-manager/globals-runtime.js +7 -7
  285. package/storybook-static/sb-manager/globals.js +1 -1
  286. package/storybook-static/sb-manager/runtime.js +88 -89
  287. package/storybook-static/vite-inject-mocker-entry.js +2 -2
  288. package/dist/chunks/picker-Cb3D2Hts.js.map +0 -1
  289. package/storybook-static/assets/FormattedTableCell-CGREP0wz.js +0 -15
  290. package/storybook-static/assets/Option-CwetjUM8.css +0 -1
  291. package/storybook-static/assets/Table.stories-ByUJbaZl.js +0 -207
  292. package/storybook-static/assets/axe-Bq-2xuso.js +0 -20
  293. package/storybook-static/assets/browserAndReact-BDUP5jYY.js +0 -70
  294. package/storybook-static/assets/check-D56EYchd.js +0 -1
  295. package/storybook-static/assets/chevron-down-CzEzTRkp.js +0 -1
  296. package/storybook-static/assets/chevron-left-Dl69q13G.js +0 -1
  297. package/storybook-static/assets/chevron-right-CJNjsAmt.js +0 -1
  298. package/storybook-static/assets/circle-check-6tyIZ3Kl.js +0 -1
  299. package/storybook-static/assets/filesAndExcel-Bs3kqlsI.js +0 -92
  300. package/storybook-static/assets/floating-ui.react-bhmHzD7p.js +0 -1
  301. package/storybook-static/assets/formatter-L2YTDE3Q-x0raBH34.js +0 -1
  302. package/storybook-static/assets/formatters-NGPd1d-h.js +0 -202
  303. package/storybook-static/assets/formatters-runtime-CCfGWt-f.js +0 -329
  304. package/storybook-static/assets/iframe-BEvUkaBB.js +0 -1
  305. package/storybook-static/assets/odata-BslPtJet.js +0 -1
  306. package/storybook-static/assets/odataAndTables-Cyl3UJOz.js +0 -77
  307. package/storybook-static/assets/pureUtilities-Bj6GraNW.js +0 -30
  308. package/storybook-static/assets/react-18-CgkwBzTo.js +0 -9
  309. package/storybook-static/assets/react-CjYyitxm.js +0 -9
  310. package/storybook-static/assets/runtimeAndState-mq-BaPyx.js +0 -93
  311. package/storybook-static/assets/syntaxhighlighter-T5IQBZDB-B5rzfkHU.js +0 -6
  312. package/storybook-static/assets/usePickerDefaultFilter-Be420WNF.js +0 -1
  313. package/storybook-static/assets/x-FZLq51ZK.js +0 -1
@@ -0,0 +1,876 @@
1
+ import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{n as t}from"./iframe-C5-IVaAZ.js";import{i as n,r}from"./react-Bl2r1tuC.js";import{l as i,m as a}from"./blocks-Dx5UE11l.js";function o(e){let t={a:`a`,code:`code`,h1:`h1`,h2:`h2`,h3:`h3`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,table:`table`,tbody:`tbody`,td:`td`,th:`th`,thead:`thead`,tr:`tr`,ul:`ul`,...n(),...e.components};return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(i,{title:`Foundation Lib/API/Binary`}),`
2
+ `,(0,c.jsxs)(t.h1,{id:`работа-с-бинарными-данными-через-ryuzaki13react-foundation-libbinary`,children:[`Работа с бинарными данными через `,(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-lib/binary`})]}),`
3
+ `,(0,c.jsxs)(t.p,{children:[`Модуль `,(0,c.jsx)(t.code,{children:`binary`}),` преобразует строковое бинарное содержимое в браузерный `,(0,c.jsx)(t.code,{children:`Blob`}),`, определяет предполагаемый MIME-тип документа и предоставляет React hook для типового сценария «base64 → `,(0,c.jsx)(t.code,{children:`{ blob, mime }`}),`».`]}),`
4
+ `,(0,c.jsx)(t.p,{children:`Основной сценарий:`}),`
5
+ `,(0,c.jsxs)(t.ol,{children:[`
6
+ `,(0,c.jsx)(t.li,{children:`backend возвращает содержимое файла строкой base64;`}),`
7
+ `,(0,c.jsx)(t.li,{children:`приложение определяет MIME-тип по имени файла, data URL или сигнатуре данных;`}),`
8
+ `,(0,c.jsx)(t.li,{children:`base64 декодируется в байты;`}),`
9
+ `,(0,c.jsxs)(t.li,{children:[`из байтов создаётся `,(0,c.jsx)(t.code,{children:`Blob`}),`;`]}),`
10
+ `,(0,c.jsxs)(t.li,{children:[`вызывающий код передаёт `,(0,c.jsx)(t.code,{children:`Blob`}),` просмотрщику, скачивает файл или отправляет его дальше.`]}),`
11
+ `]}),`
12
+ `,(0,c.jsx)(t.p,{children:`Модуль является предметно-независимым foundation-слоем. Он не знает бизнес-коды документов, не выполняет HTTP/OData-запросы, не загружает файлы с диска, не создаёт viewer и не проверяет, безопасно ли содержимое.`}),`
13
+ `,(0,c.jsx)(t.p,{children:`README рассчитан на разработчика, который использует опубликованный пакет без доступа к исходному коду. Здесь объясняются базовые понятия, все публичные функции, точный приоритет MIME, поддерживаемые форматы, ошибки, React lifecycle, безопасность и управление object URL.`}),`
14
+ `,(0,c.jsx)(t.h2,{id:`содержание`,children:`Содержание`}),`
15
+ `,(0,c.jsxs)(t.ul,{children:[`
16
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B8-%D0%B3%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%8B-%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8F`,children:`Назначение и границы модуля`})}),`
17
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D0%B8-%D0%B8%D0%BC%D0%BF%D0%BE%D1%80%D1%82`,children:`Установка и импорт`})}),`
18
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BC%D0%B8%D0%BD%D0%B8%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D0%BF%D0%BE%D0%BD%D1%8F%D1%82%D0%B8%D1%8F`,children:`Минимальные понятия`})}),`
19
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BA%D0%B0%D0%BA-%D0%B2%D1%8B%D0%B1%D1%80%D0%B0%D1%82%D1%8C-api`,children:`Как выбрать API`})}),`
20
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%B1%D1%8B%D1%81%D1%82%D1%80%D1%8B%D0%B9-%D1%81%D1%82%D0%B0%D1%80%D1%82`,children:`Быстрый старт`})}),`
21
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%B8%D0%B2%D0%B0%D0%B5%D0%BC%D1%8B%D0%B5-%D0%B2%D1%85%D0%BE%D0%B4%D0%BD%D1%8B%D0%B5-%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D1%8B`,children:`Поддерживаемые входные форматы`})}),`
22
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#binarytoblob`,children:(0,c.jsx)(t.code,{children:`binaryToBlob`})})}),`
23
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#detectmimetype`,children:(0,c.jsx)(t.code,{children:`detectMimeType`})})}),`
24
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#usebinaryfile`,children:(0,c.jsx)(t.code,{children:`useBinaryFile`})})}),`
25
+ `,(0,c.jsx)(t.li,{children:(0,c.jsxs)(t.a,{href:`#%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D1%8B%D0%BC-blob`,children:[`Работа с готовым `,(0,c.jsx)(t.code,{children:`Blob`})]})}),`
26
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D1%8B%D0%B5-%D1%80%D0%B5%D1%86%D0%B5%D0%BF%D1%82%D1%8B`,children:`Готовые рецепты`})}),`
27
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BE%D1%88%D0%B8%D0%B1%D0%BA%D0%B8-%D0%B8-%D0%B4%D0%B8%D0%B0%D0%B3%D0%BD%D0%BE%D1%81%D1%82%D0%B8%D0%BA%D0%B0`,children:`Ошибки и диагностика`})}),`
28
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D1%8C`,children:`Безопасность`})}),`
29
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D0%B8-%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D1%8C`,children:`Производительность и память`})}),`
30
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D1%82%D0%B5%D1%81%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5`,children:`Тестирование`})}),`
31
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%BA%D1%80%D0%B0%D1%82%D0%BA%D0%B8%D0%B9-%D1%81%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D1%87%D0%BD%D0%B8%D0%BA-api`,children:`Краткий справочник API`})}),`
32
+ `,(0,c.jsx)(t.li,{children:(0,c.jsx)(t.a,{href:`#%D0%B2%D0%BE%D0%BF%D1%80%D0%BE%D1%81%D1%8B-%D0%B8-%D0%BE%D1%82%D0%B2%D0%B5%D1%82%D1%8B`,children:`Вопросы и ответы`})}),`
33
+ `]}),`
34
+ `,(0,c.jsx)(t.h2,{id:`назначение-и-границы-модуля`,children:`Назначение и границы модуля`}),`
35
+ `,(0,c.jsxs)(t.h3,{id:`что-делает-binary`,children:[`Что делает `,(0,c.jsx)(t.code,{children:`binary`})]}),`
36
+ `,(0,c.jsxs)(t.ul,{children:[`
37
+ `,(0,c.jsx)(t.li,{children:`принимает base64, base64 data URL или raw binary string;`}),`
38
+ `,(0,c.jsx)(t.li,{children:`нормализует пробелы, URL-safe алфавит и отсутствующий base64 padding;`}),`
39
+ `,(0,c.jsxs)(t.li,{children:[`создаёт `,(0,c.jsx)(t.code,{children:`Blob`}),`;`]}),`
40
+ `,(0,c.jsx)(t.li,{children:`предполагает MIME по имени файла, объявлению data URL или небольшой сигнатуре;`}),`
41
+ `,(0,c.jsx)(t.li,{children:`предоставляет React hook для base64-данных.`}),`
42
+ `]}),`
43
+ `,(0,c.jsx)(t.h3,{id:`чего-модуль-не-делает`,children:`Чего модуль не делает`}),`
44
+ `,(0,c.jsxs)(t.ul,{children:[`
45
+ `,(0,c.jsx)(t.li,{children:`не отправляет запросы и не получает данные с backend;`}),`
46
+ `,(0,c.jsxs)(t.li,{children:[`не читает пользовательский `,(0,c.jsx)(t.code,{children:`File`}),` через `,(0,c.jsx)(t.code,{children:`FileReader`}),`;`]}),`
47
+ `,(0,c.jsxs)(t.li,{children:[`не скачивает `,(0,c.jsx)(t.code,{children:`Blob`}),` автоматически;`]}),`
48
+ `,(0,c.jsx)(t.li,{children:`не создаёт и не освобождает object URL;`}),`
49
+ `,(0,c.jsx)(t.li,{children:`не выполняет полную проверку формата файла;`}),`
50
+ `,(0,c.jsx)(t.li,{children:`не сканирует файл на вредоносное содержимое;`}),`
51
+ `,(0,c.jsx)(t.li,{children:`не преобразует обычный Unicode-текст в UTF-8;`}),`
52
+ `,(0,c.jsx)(t.li,{children:`не распаковывает ZIP, DOCX, XLSX или другие контейнеры;`}),`
53
+ `,(0,c.jsx)(t.li,{children:`не исправляет ошибочный MIME из внешнего источника.`}),`
54
+ `]}),`
55
+ `,(0,c.jsx)(t.h3,{id:`соседние-модули`,children:`Соседние модули`}),`
56
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Задача`}),(0,c.jsx)(t.th,{children:`Модуль`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Декодировать строковый base64/data URL в `,(0,c.jsx)(t.code,{children:`Blob`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-lib/binary`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Прочитать выбранный пользователем `,(0,c.jsx)(t.code,{children:`File`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-lib/file`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Скачать готовый `,(0,c.jsx)(t.code,{children:`Blob`}),` или object URL`]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-lib/dom`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Преобразовать base64 непосредственно в `,(0,c.jsx)(t.code,{children:`Blob`}),` без MIME-detection`]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`@ryuzaki13/react-foundation-lib/binary`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Полностью проверить структуру PDF, изображения или архива`}),(0,c.jsx)(t.td,{children:`Специализированный parser/validator на доверенной boundary`})]})]})]}),`
57
+ `,(0,c.jsxs)(t.p,{children:[`Не копируйте логику скачивания рядом с `,(0,c.jsx)(t.code,{children:`binaryToBlob`}),`. Для готового `,(0,c.jsx)(t.code,{children:`Blob`}),` уже существует `,(0,c.jsx)(t.code,{children:`downloadFileFromBlob`}),` в `,(0,c.jsx)(t.code,{children:`/dom`}),`.`]}),`
58
+ `,(0,c.jsx)(t.h2,{id:`установка-и-импорт`,children:`Установка и импорт`}),`
59
+ `,(0,c.jsx)(t.p,{children:`Установите пакет:`}),`
60
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-bash`,children:`npm install @ryuzaki13/react-foundation-lib
61
+ `})}),`
62
+ `,(0,c.jsxs)(t.p,{children:[`Импортируйте API только из опубликованного subpath `,(0,c.jsx)(t.code,{children:`/binary`}),`:`]}),`
63
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { binaryToBlob, detectMimeType, useBinaryFile } from "@ryuzaki13/react-foundation-lib/binary";
64
+ `})}),`
65
+ `,(0,c.jsx)(t.p,{children:`Корневой импорт пакета не поддерживается:`}),`
66
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`// Неправильно.
67
+ import { binaryToBlob } from "@ryuzaki13/react-foundation-lib";
68
+
69
+ // Правильно.
70
+ import { binaryToBlob } from "@ryuzaki13/react-foundation-lib/binary";
71
+ `})}),`
72
+ `,(0,c.jsx)(t.h3,{id:`react-peer-зависимость`,children:`React peer-зависимость`}),`
73
+ `,(0,c.jsxs)(t.p,{children:[`Entrypoint `,(0,c.jsx)(t.code,{children:`/binary`}),` экспортирует `,(0,c.jsx)(t.code,{children:`useBinaryFile`}),` и поэтому загружает React API. В текущем контракте пакета consumer должен предоставить совместимый React peer `,(0,c.jsx)(t.code,{children:`>=19.2.0 <20.0.0`}),`, даже если конкретный файл импортирует только `,(0,c.jsx)(t.code,{children:`binaryToBlob`}),` или `,(0,c.jsx)(t.code,{children:`detectMimeType`}),`.`]}),`
74
+ `,(0,c.jsx)(t.p,{children:`Для React-приложения зависимость обычно уже установлена:`}),`
75
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-bash`,children:`npm install react react-dom
76
+ `})}),`
77
+ `,(0,c.jsx)(t.p,{children:`Не подключайте отдельную вторую копию React ради этого модуля. Версия должна согласовываться с React host-приложения.`}),`
78
+ `,(0,c.jsx)(t.h3,{id:`runtime`,children:`Runtime`}),`
79
+ `,(0,c.jsx)(t.p,{children:`Модуль ориентирован на браузер и использует:`}),`
80
+ `,(0,c.jsxs)(t.ul,{children:[`
81
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`atob`}),`;`]}),`
82
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`Blob`}),`;`]}),`
83
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`ArrayBuffer`}),`;`]}),`
84
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`Uint8Array`}),`;`]}),`
85
+ `,(0,c.jsxs)(t.li,{children:[`React 19 hooks для `,(0,c.jsx)(t.code,{children:`useBinaryFile`}),`.`]}),`
86
+ `]}),`
87
+ `,(0,c.jsx)(t.p,{children:`В тестовой или серверной среде эти Web APIs могут отсутствовать либо вести себя иначе. Наличие похожих globals в конкретной версии Node.js не превращает browser contract в гарантированный server API.`}),`
88
+ `,(0,c.jsx)(t.h2,{id:`минимальные-понятия`,children:`Минимальные понятия`}),`
89
+ `,(0,c.jsx)(t.h3,{id:`байт`,children:`Байт`}),`
90
+ `,(0,c.jsxs)(t.p,{children:[`Байт — целое число от `,(0,c.jsx)(t.code,{children:`0`}),` до `,(0,c.jsx)(t.code,{children:`255`}),`. Файл на низком уровне является последовательностью байтов.`]}),`
91
+ `,(0,c.jsxs)(t.p,{children:[`Например, ASCII-строка `,(0,c.jsx)(t.code,{children:`"ABC"`}),` представлена байтами:`]}),`
92
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Символ`}),(0,c.jsx)(t.th,{style:{textAlign:`right`},children:`Код байта`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`A`})}),(0,c.jsx)(t.td,{style:{textAlign:`right`},children:(0,c.jsx)(t.code,{children:`65`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`B`})}),(0,c.jsx)(t.td,{style:{textAlign:`right`},children:(0,c.jsx)(t.code,{children:`66`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`C`})}),(0,c.jsx)(t.td,{style:{textAlign:`right`},children:(0,c.jsx)(t.code,{children:`67`})})]})]})]}),`
93
+ `,(0,c.jsx)(t.h3,{id:`бинарные-данные`,children:`Бинарные данные`}),`
94
+ `,(0,c.jsx)(t.p,{children:`Бинарные данные — произвольные байты файла: PDF, изображения, архивы, офисные документы и так далее. Не каждый набор байтов является корректным текстом.`}),`
95
+ `,(0,c.jsx)(t.h3,{id:`base64`,children:`Base64`}),`
96
+ `,(0,c.jsx)(t.p,{children:`Base64 кодирует байты ограниченным набором печатных символов:`}),`
97
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`ABCDEFGHIJKLMNOPQRSTUVWXYZ
98
+ abcdefghijklmnopqrstuvwxyz
99
+ 0123456789
100
+ +/
101
+ `})}),`
102
+ `,(0,c.jsx)(t.p,{children:`Пример:`}),`
103
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`байты текста "Hello" → SGVsbG8=
104
+ `})}),`
105
+ `,(0,c.jsx)(t.p,{children:`Base64 не шифрует данные и не делает их безопасными. Любой, кто получил строку, может декодировать содержимое.`}),`
106
+ `,(0,c.jsxs)(t.h3,{id:`padding-`,children:[`Padding `,(0,c.jsx)(t.code,{children:`=`})]}),`
107
+ `,(0,c.jsxs)(t.p,{children:[`В конце стандартного base64 могут находиться один или два символа `,(0,c.jsx)(t.code,{children:`=`}),`. Они дополняют длину строки до блока из четырёх символов.`]}),`
108
+ `,(0,c.jsx)(t.p,{children:`Модуль умеет добавить отсутствующий padding:`}),`
109
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`SGVsbG8 → SGVsbG8=
110
+ `})}),`
111
+ `,(0,c.jsxs)(t.p,{children:[`Строка, длина которой после нормализации даёт остаток `,(0,c.jsx)(t.code,{children:`1`}),` при делении на `,(0,c.jsx)(t.code,{children:`4`}),`, не может быть корректно дополнена и отклоняется.`]}),`
112
+ `,(0,c.jsx)(t.h3,{id:`url-safe-base64`,children:`URL-safe base64`}),`
113
+ `,(0,c.jsx)(t.p,{children:`URL-safe вариант заменяет:`}),`
114
+ `,(0,c.jsxs)(t.ul,{children:[`
115
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`+`}),` на `,(0,c.jsx)(t.code,{children:`-`}),`;`]}),`
116
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`/`}),` на `,(0,c.jsx)(t.code,{children:`_`}),`.`]}),`
117
+ `]}),`
118
+ `,(0,c.jsx)(t.p,{children:`Модуль возвращает эти символы в стандартный base64-алфавит перед декодированием.`}),`
119
+ `,(0,c.jsx)(t.h3,{id:`data-url`,children:`Data URL`}),`
120
+ `,(0,c.jsx)(t.p,{children:`Data URL содержит metadata и данные в одной строке:`}),`
121
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`data:application/pdf;base64,JVBERi0xLjc...
122
+ `})}),`
123
+ `,(0,c.jsx)(t.p,{children:`Структура:`}),`
124
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`data:<MIME>;base64,<payload>
125
+ `})}),`
126
+ `,(0,c.jsxs)(t.p,{children:[`Модуль поддерживает только base64 data URL с обязательным маркером `,(0,c.jsx)(t.code,{children:`;base64,`}),`. Обычный percent-encoded data URL вида `,(0,c.jsx)(t.code,{children:`data:text/plain,Hello%20world`}),` не поддерживается.`]}),`
127
+ `,(0,c.jsx)(t.h3,{id:`mime-тип`,children:`MIME-тип`}),`
128
+ `,(0,c.jsx)(t.p,{children:`MIME сообщает, как интерпретировать содержимое:`}),`
129
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`MIME`}),(0,c.jsx)(t.th,{children:`Тип содержимого`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/pdf`})}),(0,c.jsx)(t.td,{children:`PDF`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/png`})}),(0,c.jsx)(t.td,{children:`PNG`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`text/plain`})}),(0,c.jsx)(t.td,{children:`Обычный текст`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/zip`})}),(0,c.jsx)(t.td,{children:`ZIP`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/octet-stream`})}),(0,c.jsx)(t.td,{children:`Неопределённые бинарные данные`})]})]})]}),`
130
+ `,(0,c.jsxs)(t.p,{children:[`MIME — metadata, а не доказательство реального формата. Строка может заявлять `,(0,c.jsx)(t.code,{children:`image/png`}),`, хотя внутри находится другой файл.`]}),`
131
+ `,(0,c.jsx)(t.h3,{id:`blob`,children:(0,c.jsx)(t.code,{children:`Blob`})}),`
132
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`Blob`}),` — браузерный объект, который хранит последовательность байтов и MIME:`]}),`
133
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = new Blob([new Uint8Array([65, 66, 67])], { type: "text/plain" });
134
+ `})}),`
135
+ `,(0,c.jsxs)(t.p,{children:[`У `,(0,c.jsx)(t.code,{children:`Blob`}),` есть:`]}),`
136
+ `,(0,c.jsxs)(t.ul,{children:[`
137
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`blob.type`}),` — MIME;`]}),`
138
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`blob.size`}),` — размер в байтах;`]}),`
139
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`blob.text()`}),` — прочитать как текст;`]}),`
140
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`blob.arrayBuffer()`}),` — получить байты.`]}),`
141
+ `]}),`
142
+ `,(0,c.jsx)(t.h3,{id:`object-url`,children:`Object URL`}),`
143
+ `,(0,c.jsxs)(t.p,{children:[`Object URL — временная браузерная ссылка на `,(0,c.jsx)(t.code,{children:`Blob`}),`:`]}),`
144
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const objectUrl = URL.createObjectURL(blob);
145
+ `})}),`
146
+ `,(0,c.jsx)(t.p,{children:`Она похожа на:`}),`
147
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`blob:https://example.test/...
148
+ `})}),`
149
+ `,(0,c.jsx)(t.p,{children:`Object URL не содержит base64 и не является data URL. После использования его нужно освободить:`}),`
150
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`URL.revokeObjectURL(objectUrl);
151
+ `})}),`
152
+ `,(0,c.jsxs)(t.p,{children:[`Сам `,(0,c.jsx)(t.code,{children:`Blob`}),` не требует ручного `,(0,c.jsx)(t.code,{children:`revoke`}),`; освобождать нужно созданные через `,(0,c.jsx)(t.code,{children:`URL.createObjectURL`}),` URL.`]}),`
153
+ `,(0,c.jsx)(t.h3,{id:`raw-binary-string`,children:`Raw binary string`}),`
154
+ `,(0,c.jsx)(t.p,{children:`Raw binary string — JavaScript-строка, в которой код каждого символа рассматривается как один байт.`}),`
155
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const raw = String.fromCharCode(65, 66, 67);
156
+ `})}),`
157
+ `,(0,c.jsx)(t.p,{children:`Это не обычная Unicode-строка и не UTF-8. Режим нужен только для legacy API, которые уже вернули байты в такой форме.`}),`
158
+ `,(0,c.jsx)(t.h2,{id:`как-выбрать-api`,children:`Как выбрать API`}),`
159
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Нужно`}),(0,c.jsx)(t.th,{children:`Использовать`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Превратить base64 в `,(0,c.jsx)(t.code,{children:`Blob`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`binaryToBlob`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Превратить base64 data URL в `,(0,c.jsx)(t.code,{children:`Blob`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`binaryToBlob`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Превратить raw binary string в `,(0,c.jsx)(t.code,{children:`Blob`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`binaryToBlob(..., ..., false)`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Предположить MIME по имени и данным`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`detectMimeType`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`В React получить `,(0,c.jsx)(t.code,{children:`{ blob, mime }`}),` из base64 prop/state`]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`useBinaryFile`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Скачать готовый `,(0,c.jsx)(t.code,{children:`Blob`})]}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`downloadFileFromBlob`}),` из `,(0,c.jsx)(t.code,{children:`/dom`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Прочитать пользовательский `,(0,c.jsx)(t.code,{children:`File`})]}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`readFile`}),` или `,(0,c.jsx)(t.code,{children:`readImageFile`}),` из `,(0,c.jsx)(t.code,{children:`/file`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Использовать известные filename и MIME`}),(0,c.jsxs)(t.td,{children:[`Вызвать `,(0,c.jsx)(t.code,{children:`detectMimeType`}),`/`,(0,c.jsx)(t.code,{children:`binaryToBlob`}),` вручную`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Полностью проверить файл`}),(0,c.jsxs)(t.td,{children:[`Специализированный validator, не `,(0,c.jsx)(t.code,{children:`detectMimeType`})]})]})]})]}),`
160
+ `,(0,c.jsx)(t.h2,{id:`быстрый-старт`,children:`Быстрый старт`}),`
161
+ `,(0,c.jsx)(t.h3,{id:`base64-и-имя-файла`,children:`Base64 и имя файла`}),`
162
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { binaryToBlob, detectMimeType } from "@ryuzaki13/react-foundation-lib/binary";
163
+ import { downloadFileFromBlob } from "@ryuzaki13/react-foundation-lib/dom";
164
+
165
+ type BackendFile = {
166
+ fileName: string;
167
+ fileContent: string;
168
+ };
169
+
170
+ function downloadBackendFile(file: BackendFile) {
171
+ const mime = detectMimeType(file.fileName, file.fileContent);
172
+ const blob = binaryToBlob(file.fileContent, mime);
173
+
174
+ downloadFileFromBlob(file.fileName, blob);
175
+ }
176
+ `})}),`
177
+ `,(0,c.jsx)(t.h3,{id:`base64-data-url`,children:`Base64 data URL`}),`
178
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const dataUrl = "data:text/plain;base64,SGVsbG8=";
179
+
180
+ const mime = detectMimeType(undefined, dataUrl);
181
+ const blob = binaryToBlob(dataUrl, mime);
182
+
183
+ console.log(mime); // "text/plain"
184
+ console.log(blob.type); // "text/plain"
185
+ console.log(await blob.text()); // "Hello"
186
+ `})}),`
187
+ `,(0,c.jsxs)(t.p,{children:[`Важно: `,(0,c.jsx)(t.code,{children:`binaryToBlob(dataUrl)`}),` самостоятельно не возьмёт MIME из data URL. Без второго аргумента `,(0,c.jsx)(t.code,{children:`blob.type`}),` будет `,(0,c.jsx)(t.code,{children:`application/octet-stream`}),`.`]}),`
188
+ `,(0,c.jsx)(t.h3,{id:`общий-поток`,children:`Общий поток`}),`
189
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`fileName ───────────────────────┐
190
+ ├─> detectMimeType ─> MIME ─┐
191
+ base64 / base64 data URL ──────┘ │
192
+ ├─> Blob
193
+ base64 / base64 data URL ─────────> binaryToBlob ─────────┘
194
+
195
+ ├─> viewer
196
+ ├─> download
197
+ └─> FormData
198
+ `})}),`
199
+ `,(0,c.jsx)(t.h2,{id:`поддерживаемые-входные-форматы`,children:`Поддерживаемые входные форматы`}),`
200
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Вход`}),(0,c.jsx)(t.th,{children:`Поддержка`}),(0,c.jsx)(t.th,{children:`Пример/комментарий`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Стандартный base64`}),(0,c.jsx)(t.td,{children:`Да`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`SGVsbG8=`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Base64 без padding`}),(0,c.jsx)(t.td,{children:`Да`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`SGVsbG8`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Base64 с пробелами и переносами`}),(0,c.jsx)(t.td,{children:`Да`}),(0,c.jsx)(t.td,{children:`Пробельные символы удаляются`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`URL-safe base64`}),(0,c.jsx)(t.td,{children:`Да`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`-`}),` и `,(0,c.jsx)(t.code,{children:`_`}),` заменяются на `,(0,c.jsx)(t.code,{children:`+`}),` и `,(0,c.jsx)(t.code,{children:`/`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Base64 data URL`}),(0,c.jsx)(t.td,{children:`Да`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`data:image/png;base64,...`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Data URL с параметрами`}),(0,c.jsx)(t.td,{children:`Да`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`data:text/plain;charset=utf-8;base64,...`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Data URL без MIME`}),(0,c.jsx)(t.td,{children:`Да`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`data:;base64,...`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Raw binary string`}),(0,c.jsxs)(t.td,{children:[`Да, только с `,(0,c.jsx)(t.code,{children:`isBase64 = false`})]}),(0,c.jsx)(t.td,{children:`Каждый JS-символ превращается в один байт`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Обычная Unicode-строка`}),(0,c.jsx)(t.td,{children:`Нет как raw binary`}),(0,c.jsx)(t.td,{children:`Это не UTF-8 encoder`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Percent-encoded data URL`}),(0,c.jsx)(t.td,{children:`Нет`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`data:text/plain,Hello%20world`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Hex-строка`}),(0,c.jsx)(t.td,{children:`Нет`}),(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`25504446`}),` не трактуется как байты PDF`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`Uint8Array`})}),(0,c.jsx)(t.td,{children:`Нет`}),(0,c.jsxs)(t.td,{children:[`API принимает `,(0,c.jsx)(t.code,{children:`string`}),`; создайте `,(0,c.jsx)(t.code,{children:`Blob`}),` напрямую`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`ArrayBuffer`})}),(0,c.jsx)(t.td,{children:`Нет`}),(0,c.jsxs)(t.td,{children:[`API принимает `,(0,c.jsx)(t.code,{children:`string`}),`; создайте `,(0,c.jsx)(t.code,{children:`Blob`}),` напрямую`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Пустая строка`}),(0,c.jsx)(t.td,{children:`Нет`}),(0,c.jsx)(t.td,{children:`Выбрасывается ошибка`})]})]})]}),`
201
+ `,(0,c.jsx)(t.h2,{id:`binarytoblob`,children:(0,c.jsx)(t.code,{children:`binaryToBlob`})}),`
202
+ `,(0,c.jsx)(t.h3,{id:`сигнатура`,children:`Сигнатура`}),`
203
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function binaryToBlob(binaryData: string, mimeType?: string, isBase64?: boolean): Blob;
204
+ `})}),`
205
+ `,(0,c.jsx)(t.p,{children:`Фактические значения по умолчанию:`}),`
206
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`mimeType = "application/octet-stream";
207
+ isBase64 = true;
208
+ `})}),`
209
+ `,(0,c.jsx)(t.h3,{id:`параметры`,children:`Параметры`}),`
210
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Параметр`}),(0,c.jsx)(t.th,{children:`Тип`}),(0,c.jsx)(t.th,{children:`По умолчанию`}),(0,c.jsx)(t.th,{children:`Назначение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`binaryData`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`string`})}),(0,c.jsx)(t.td,{children:`Обязательный`}),(0,c.jsx)(t.td,{children:`Base64/data URL или raw binary string`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`mimeType`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`string`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/octet-stream`})}),(0,c.jsxs)(t.td,{children:[`MIME создаваемого `,(0,c.jsx)(t.code,{children:`Blob`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`isBase64`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`boolean`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`true`})}),(0,c.jsx)(t.td,{children:`Декодировать base64 или читать коды символов как байты`})]})]})]}),`
211
+ `,(0,c.jsx)(t.h3,{id:`результат`,children:`Результат`}),`
212
+ `,(0,c.jsxs)(t.p,{children:[`Возвращается новый непустой `,(0,c.jsx)(t.code,{children:`Blob`}),`.`]}),`
213
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = binaryToBlob("SGVsbG8=", "text/plain");
214
+
215
+ console.log(blob.size); // 5
216
+ console.log(blob.type); // "text/plain"
217
+ console.log(await blob.text()); // "Hello"
218
+ `})}),`
219
+ `,(0,c.jsxs)(t.p,{children:[`Функция синхронная. Методы чтения самого `,(0,c.jsx)(t.code,{children:`Blob`}),`, например `,(0,c.jsx)(t.code,{children:`text()`}),` и `,(0,c.jsx)(t.code,{children:`arrayBuffer()`}),`, возвращают `,(0,c.jsx)(t.code,{children:`Promise`}),`.`]}),`
220
+ `,(0,c.jsx)(t.h3,{id:`что-происходит-в-base64-режиме`,children:`Что происходит в base64-режиме`}),`
221
+ `,(0,c.jsxs)(t.p,{children:[`При `,(0,c.jsx)(t.code,{children:`isBase64 = true`}),` функция:`]}),`
222
+ `,(0,c.jsxs)(t.ol,{children:[`
223
+ `,(0,c.jsx)(t.li,{children:`проверяет, не является ли строка base64 data URL;`}),`
224
+ `,(0,c.jsx)(t.li,{children:`для data URL отделяет payload после запятой;`}),`
225
+ `,(0,c.jsx)(t.li,{children:`удаляет все пробельные символы;`}),`
226
+ `,(0,c.jsxs)(t.li,{children:[`заменяет URL-safe `,(0,c.jsx)(t.code,{children:`-`}),` и `,(0,c.jsx)(t.code,{children:`_`}),`;`]}),`
227
+ `,(0,c.jsx)(t.li,{children:`проверяет допустимый алфавит и padding;`}),`
228
+ `,(0,c.jsx)(t.li,{children:`добавляет отсутствующий padding;`}),`
229
+ `,(0,c.jsxs)(t.li,{children:[`декодирует строку браузерным `,(0,c.jsx)(t.code,{children:`atob`}),`;`]}),`
230
+ `,(0,c.jsxs)(t.li,{children:[`переносит коды полученной binary string в `,(0,c.jsx)(t.code,{children:`Uint8Array`}),`;`]}),`
231
+ `,(0,c.jsxs)(t.li,{children:[`копирует байты в отдельный `,(0,c.jsx)(t.code,{children:`ArrayBuffer`}),`;`]}),`
232
+ `,(0,c.jsxs)(t.li,{children:[`создаёт `,(0,c.jsx)(t.code,{children:`Blob`}),` с переданным MIME.`]}),`
233
+ `]}),`
234
+ `,(0,c.jsx)(t.h3,{id:`обычный-base64`,children:`Обычный base64`}),`
235
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = binaryToBlob("SGVsbG8=", "text/plain");
236
+
237
+ console.log(await blob.text()); // "Hello"
238
+ `})}),`
239
+ `,(0,c.jsx)(t.h3,{id:`пробелы-и-переносы-строк`,children:`Пробелы и переносы строк`}),`
240
+ `,(0,c.jsx)(t.p,{children:`Пробельные символы удаляются во всей base64-строке:`}),`
241
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = binaryToBlob("SGVs\\n bG8=\\t", "text/plain");
242
+
243
+ console.log(await blob.text()); // "Hello"
244
+ `})}),`
245
+ `,(0,c.jsxs)(t.p,{children:[`Это удобно для MIME-wrapped base64, но не исправляет данные, в которых символ `,(0,c.jsx)(t.code,{children:`+`}),` был случайно заменён пробелом при URL/form-декодировании. В таком случае байт будет потерян.`]}),`
246
+ `,(0,c.jsx)(t.h3,{id:`отсутствующий-padding`,children:`Отсутствующий padding`}),`
247
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = binaryToBlob("SGVsbG8", "text/plain");
248
+
249
+ console.log(await blob.text()); // "Hello"
250
+ `})}),`
251
+ `,(0,c.jsx)(t.h3,{id:`url-safe-base64-1`,children:`URL-safe base64`}),`
252
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = binaryToBlob("__8", "application/octet-stream");
253
+
254
+ const bytes = new Uint8Array(await blob.arrayBuffer());
255
+
256
+ console.log([...bytes]); // [255, 255]
257
+ `})}),`
258
+ `,(0,c.jsx)(t.h3,{id:`data-url-1`,children:`Data URL`}),`
259
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const dataUrl = "data:text/plain;base64,SGVsbG8=";
260
+
261
+ const blob = binaryToBlob(dataUrl, "text/plain");
262
+
263
+ console.log(await blob.text()); // "Hello"
264
+ `})}),`
265
+ `,(0,c.jsx)(t.p,{children:`Поддерживается data URL с дополнительными параметрами:`}),`
266
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const dataUrl = "data:text/plain;charset=utf-8;base64,SGVsbG8=";
267
+ `})}),`
268
+ `,(0,c.jsxs)(t.p,{children:[`Распознавание префикса выполняется без учёта регистра для `,(0,c.jsx)(t.code,{children:`data:`}),` и `,(0,c.jsx)(t.code,{children:`base64`}),`.`]}),`
269
+ `,(0,c.jsx)(t.h3,{id:`mime-data-url-не-применяется-автоматически`,children:`MIME data URL не применяется автоматически`}),`
270
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`binaryToBlob`}),` отделяет payload data URL, но намеренно использует только аргумент `,(0,c.jsx)(t.code,{children:`mimeType`}),`:`]}),`
271
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const dataUrl = "data:image/png;base64,iVBORw0KGgo=";
272
+
273
+ const blob = binaryToBlob(dataUrl);
274
+
275
+ console.log(blob.type);
276
+ // "application/octet-stream"
277
+ `})}),`
278
+ `,(0,c.jsxs)(t.p,{children:[`Для использования MIME из data URL сначала вызовите `,(0,c.jsx)(t.code,{children:`detectMimeType`}),`:`]}),`
279
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const mime = detectMimeType(undefined, dataUrl);
280
+ const blob = binaryToBlob(dataUrl, mime);
281
+ `})}),`
282
+ `,(0,c.jsx)(t.h3,{id:`пустой-mime`,children:`Пустой MIME`}),`
283
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`undefined`}),`, пустая строка или строка только из пробелов приводят к `,(0,c.jsx)(t.code,{children:`application/octet-stream`}),`:`]}),`
284
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`binaryToBlob("SGVsbG8=", undefined).type;
285
+ // "application/octet-stream"
286
+
287
+ binaryToBlob("SGVsbG8=", "").type;
288
+ // "application/octet-stream"
289
+
290
+ binaryToBlob("SGVsbG8=", " ").type;
291
+ // "application/octet-stream"
292
+ `})}),`
293
+ `,(0,c.jsxs)(t.p,{children:[`Непустой MIME передаётся в конструктор `,(0,c.jsx)(t.code,{children:`Blob`}),` после `,(0,c.jsx)(t.code,{children:`trim()`}),`. Окончательная нормализация `,(0,c.jsx)(t.code,{children:`blob.type`}),` выполняется браузерной реализацией `,(0,c.jsx)(t.code,{children:`Blob`}),`.`]}),`
294
+ `,(0,c.jsx)(t.h3,{id:`raw-binary-string-1`,children:`Raw binary string`}),`
295
+ `,(0,c.jsx)(t.p,{children:`Чтобы отключить base64-декодирование:`}),`
296
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = binaryToBlob("ABC", "application/octet-stream", false);
297
+
298
+ const bytes = new Uint8Array(await blob.arrayBuffer());
299
+
300
+ console.log([...bytes]); // [65, 66, 67]
301
+ `})}),`
302
+ `,(0,c.jsxs)(t.p,{children:[`Каждый UTF-16 code unit строки записывается в `,(0,c.jsx)(t.code,{children:`Uint8Array`}),`. Значения больше `,(0,c.jsx)(t.code,{children:`255`}),` обрезаются до младшего байта.`]}),`
303
+ `,(0,c.jsx)(t.p,{children:`Поэтому обычный Unicode-текст нельзя передавать как raw binary:`}),`
304
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`// Неправильно для UTF-8.
305
+ binaryToBlob("Привет", "text/plain", false);
306
+ `})}),`
307
+ `,(0,c.jsxs)(t.p,{children:[`Для текста используйте `,(0,c.jsx)(t.code,{children:`TextEncoder`}),` и создайте `,(0,c.jsx)(t.code,{children:`Blob`}),` напрямую:`]}),`
308
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const bytes = new TextEncoder().encode("Привет");
309
+ const blob = new Blob([bytes], { type: "text/plain;charset=utf-8" });
310
+ `})}),`
311
+ `,(0,c.jsx)(t.h3,{id:`функция-не-выполняет-mime-detection`,children:`Функция не выполняет MIME-detection`}),`
312
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = binaryToBlob(pdfBase64);
313
+
314
+ console.log(blob.type);
315
+ // "application/octet-stream", даже если внутри PDF.
316
+ `})}),`
317
+ `,(0,c.jsx)(t.p,{children:`Если MIME неизвестен:`}),`
318
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const mime = detectMimeType(fileName, pdfBase64);
319
+ const blob = binaryToBlob(pdfBase64, mime);
320
+ `})}),`
321
+ `,(0,c.jsx)(t.h3,{id:`ошибки`,children:`Ошибки`}),`
322
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Условие`}),(0,c.jsx)(t.th,{children:`Сообщение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`binaryData === ""`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`Не переданы бинарные данные`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`После удаления префикса/пробелов payload пуст`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`После преобразования не осталось данных`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Недопустимый base64-символ`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`Некорректный формат base64`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Длина base64 имеет невозможный остаток`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`Некорректный формат base64`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`atob`}),` отклонил редкий синтаксически прошедший вариант`]}),(0,c.jsxs)(t.td,{children:[`Сообщение browser `,(0,c.jsx)(t.code,{children:`DOMException`})]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`Низкоуровневый API выбросил не-`,(0,c.jsx)(t.code,{children:`Error`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`Некорректный формат бинарных данных`})})]})]})]}),`
323
+ `,(0,c.jsx)(t.p,{children:`Пример обработки:`}),`
324
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`try {
325
+ const blob = binaryToBlob(payload, "application/pdf");
326
+
327
+ showDocument(blob);
328
+ } catch (error) {
329
+ const message = error instanceof Error ? error.message : "Не удалось декодировать файл";
330
+
331
+ showError(message);
332
+ }
333
+ `})}),`
334
+ `,(0,c.jsx)(t.p,{children:`Не включайте исходную base64-строку в сообщение, лог или error report: она может содержать персональные или конфиденциальные данные.`}),`
335
+ `,(0,c.jsx)(t.h2,{id:`detectmimetype`,children:(0,c.jsx)(t.code,{children:`detectMimeType`})}),`
336
+ `,(0,c.jsx)(t.h3,{id:`сигнатура-1`,children:`Сигнатура`}),`
337
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function detectMimeType(fileName?: string, binaryData?: string): string;
338
+ `})}),`
339
+ `,(0,c.jsxs)(t.p,{children:[`Функция всегда возвращает строку и не выбрасывает ошибку для неизвестного либо некорректного base64. Если MIME определить не удалось, возвращается `,(0,c.jsx)(t.code,{children:`application/pdf`}),`.`]}),`
340
+ `,(0,c.jsx)(t.h3,{id:`приоритет-источников`,children:`Приоритет источников`}),`
341
+ `,(0,c.jsx)(t.p,{children:`Проверки выполняются строго в таком порядке:`}),`
342
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{style:{textAlign:`right`},children:`Приоритет`}),(0,c.jsx)(t.th,{children:`Источник`}),(0,c.jsx)(t.th,{children:`Когда используется`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{style:{textAlign:`right`},children:`1`}),(0,c.jsxs)(t.td,{children:[`Расширение `,(0,c.jsx)(t.code,{children:`fileName`})]}),(0,c.jsx)(t.td,{children:`Расширение известно таблице`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{style:{textAlign:`right`},children:`2`}),(0,c.jsx)(t.td,{children:`MIME из base64 data URL`}),(0,c.jsx)(t.td,{children:`Filename не дал известный MIME`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{style:{textAlign:`right`},children:`3`}),(0,c.jsx)(t.td,{children:`Сигнатура декодированных данных`}),(0,c.jsx)(t.td,{children:`Data URL не объявил непустой MIME`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{style:{textAlign:`right`},children:`4`}),(0,c.jsx)(t.td,{children:`Fallback PDF`}),(0,c.jsx)(t.td,{children:`Ничего не распознано`})]})]})]}),`
343
+ `,(0,c.jsx)(t.p,{children:`Первый успешный источник побеждает. Функция не сравнивает источники между собой.`}),`
344
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const pngDataUrl = "data:image/png;base64,iVBORw0KGgo=";
345
+
346
+ detectMimeType("report.pdf", pngDataUrl);
347
+ // "application/pdf": расширение filename имеет приоритет.
348
+ `})}),`
349
+ `,(0,c.jsx)(t.h3,{id:`mime-по-расширению-файла`,children:`MIME по расширению файла`}),`
350
+ `,(0,c.jsx)(t.p,{children:`Поддерживается последняя часть имени после точки. Регистр не важен.`}),`
351
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Расширение`}),(0,c.jsx)(t.th,{children:`MIME`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`bmp`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/bmp`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`csv`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`text/csv`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`doc`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/msword`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`docx`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/vnd.openxmlformats-officedocument.wordprocessingml.document`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`gif`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/gif`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`jpeg`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/jpeg`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`jpg`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/jpeg`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`json`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/json`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`pdf`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/pdf`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`png`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/png`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`ppt`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/vnd.ms-powerpoint`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`pptx`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/vnd.openxmlformats-officedocument.presentationml.presentation`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`svg`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/svg+xml`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`tif`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/tiff`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`tiff`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/tiff`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`txt`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`text/plain`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`webp`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/webp`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`xls`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/vnd.ms-excel`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`xlsx`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`xml`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/xml`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`zip`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/zip`})})]})]})]}),`
352
+ `,(0,c.jsx)(t.p,{children:`Примеры:`}),`
353
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`detectMimeType("report.xlsx");
354
+ // "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
355
+
356
+ detectMimeType("PHOTO.JPG");
357
+ // "image/jpeg"
358
+
359
+ detectMimeType("archive.backup.zip");
360
+ // "application/zip"
361
+ `})}),`
362
+ `,(0,c.jsx)(t.p,{children:`Filename не очищается от query/hash и пробелов:`}),`
363
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`detectMimeType("photo.jpg?download=1");
364
+ // "application/pdf", если binaryData не передан.
365
+
366
+ detectMimeType("photo.jpg ");
367
+ // "application/pdf", если binaryData не передан.
368
+ `})}),`
369
+ `,(0,c.jsx)(t.p,{children:`Передавайте именно имя файла, а не URL. Если есть URL, сначала безопасно извлеките pathname/filename на соответствующей boundary.`}),`
370
+ `,(0,c.jsx)(t.h3,{id:`mime-из-data-url`,children:`MIME из data URL`}),`
371
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const dataUrl = "data:image/png;base64,iVBORw0KGgo=";
372
+
373
+ detectMimeType(undefined, dataUrl);
374
+ // "image/png"
375
+ `})}),`
376
+ `,(0,c.jsxs)(t.p,{children:[`Для параметров используется только часть до первого `,(0,c.jsx)(t.code,{children:`;`}),`:`]}),`
377
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const dataUrl = "data:text/plain;charset=utf-8;base64,SGVsbG8=";
378
+
379
+ detectMimeType(undefined, dataUrl);
380
+ // "text/plain"
381
+ `})}),`
382
+ `,(0,c.jsx)(t.p,{children:`Если MIME пуст:`}),`
383
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const dataUrl = "data:;base64,JVBERi0xLjc=";
384
+
385
+ detectMimeType(undefined, dataUrl);
386
+ // Проверка продолжится по сигнатуре.
387
+ `})}),`
388
+ `,(0,c.jsx)(t.p,{children:`Объявленный MIME возвращается без декодирования и проверки payload:`}),`
389
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`detectMimeType(undefined, "data:image/png;base64,not-valid-base64");
390
+ // "image/png"
391
+ `})}),`
392
+ `,(0,c.jsx)(t.p,{children:`Поэтому data URL MIME нельзя считать доказательством формата.`}),`
393
+ `,(0,c.jsx)(t.h3,{id:`mime-по-сигнатуре`,children:`MIME по сигнатуре`}),`
394
+ `,(0,c.jsx)(t.p,{children:`Если filename и data URL не дали тип, функция пытается декодировать начало base64. Ошибка декодирования скрывается, после чего используется fallback.`}),`
395
+ `,(0,c.jsx)(t.p,{children:`Проверяются следующие признаки:`}),`
396
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Начало данных`}),(0,c.jsx)(t.th,{children:`Результат`}),(0,c.jsx)(t.th,{children:`Ограничение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`bytes `,(0,c.jsx)(t.code,{children:`25 50 44 46`}),` (`,(0,c.jsx)(t.code,{children:`%PDF`}),`)`]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/pdf`})}),(0,c.jsx)(t.td,{children:`Проверяются только первые четыре байта`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`bytes `,(0,c.jsx)(t.code,{children:`FF D8 FF`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/jpeg`})}),(0,c.jsx)(t.td,{children:`Проверяются только первые три байта`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`bytes `,(0,c.jsx)(t.code,{children:`89 50 4E 47`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/png`})}),(0,c.jsx)(t.td,{children:`Полная восьмибайтовая PNG signature не проверяется`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`текст `,(0,c.jsx)(t.code,{children:`GIF`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/gif`})}),(0,c.jsxs)(t.td,{children:[`Версия `,(0,c.jsx)(t.code,{children:`87a/89a`}),` не проверяется`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`текст `,(0,c.jsx)(t.code,{children:`RIFF`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`image/webp`})}),(0,c.jsxs)(t.td,{children:[`Маркер `,(0,c.jsx)(t.code,{children:`WEBP`}),` дальше в header не проверяется`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`bytes `,(0,c.jsx)(t.code,{children:`50 4B`}),` (`,(0,c.jsx)(t.code,{children:`PK`}),`)`]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/zip`})}),(0,c.jsx)(t.td,{children:`OOXML-файлы без filename тоже выглядят как ZIP`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[`первый непустой текст начинается с `,(0,c.jsx)(t.code,{children:`<?xml`}),` или `,(0,c.jsx)(t.code,{children:`<`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/xml`})}),(0,c.jsx)(t.td,{children:`HTML и SVG тоже могут попасть в эту ветку`})]})]})]}),`
397
+ `,(0,c.jsx)(t.p,{children:`Примеры:`}),`
398
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`detectMimeType(undefined, pdfBase64);
399
+ // "application/pdf"
400
+
401
+ detectMimeType(undefined, jpegBase64);
402
+ // "image/jpeg"
403
+
404
+ detectMimeType(undefined, zipBase64);
405
+ // "application/zip"
406
+ `})}),`
407
+ `,(0,c.jsxs)(t.p,{children:[`DOCX, XLSX и PPTX являются ZIP-контейнерами. Без имени файла они обычно определятся как `,(0,c.jsx)(t.code,{children:`application/zip`}),`, а не как конкретный Office MIME.`]}),`
408
+ `,(0,c.jsxs)(t.p,{children:[`Любое RIFF-содержимое соответствует текущей короткой проверке и может быть ошибочно определено как `,(0,c.jsx)(t.code,{children:`image/webp`}),`. Например, WAV/AVI без filename не должны доверять этому результату.`]}),`
409
+ `,(0,c.jsxs)(t.p,{children:[`Текст, начинающийся после пробелов с `,(0,c.jsx)(t.code,{children:`<`}),`, считается XML-подобным. Это эвристика, а не XML parser.`]}),`
410
+ `,(0,c.jsx)(t.h3,{id:`fallback`,children:`Fallback`}),`
411
+ `,(0,c.jsx)(t.p,{children:`Если ничего не распознано:`}),`
412
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`detectMimeType();
413
+ // "application/pdf"
414
+
415
+ detectMimeType(undefined, "не base64");
416
+ // "application/pdf"
417
+
418
+ detectMimeType("unknown.bin");
419
+ // "application/pdf"
420
+ `})}),`
421
+ `,(0,c.jsx)(t.p,{children:`Fallback PDF является осознанным предметно-независимым default текущего контракта, оптимизированным под документные сценарии пакета. Это не означает, что неизвестные данные действительно являются PDF.`}),`
422
+ `,(0,c.jsx)(t.p,{children:`Если вызывающий код не может принимать такое предположение, он должен:`}),`
423
+ `,(0,c.jsxs)(t.ul,{children:[`
424
+ `,(0,c.jsx)(t.li,{children:`требовать известный MIME от backend;`}),`
425
+ `,(0,c.jsx)(t.li,{children:`валидировать формат специализированным parser;`}),`
426
+ `,(0,c.jsx)(t.li,{children:`или применять собственный fallback после отдельной проверки.`}),`
427
+ `]}),`
428
+ `,(0,c.jsxs)(t.h3,{id:`detectmimetype-не-является-validator`,children:[(0,c.jsx)(t.code,{children:`detectMimeType`}),` не является validator`]}),`
429
+ `,(0,c.jsx)(t.p,{children:`Функция отвечает только на вопрос «какой MIME предположить». Она не отвечает на вопросы:`}),`
430
+ `,(0,c.jsxs)(t.ul,{children:[`
431
+ `,(0,c.jsx)(t.li,{children:`полностью ли корректен файл;`}),`
432
+ `,(0,c.jsx)(t.li,{children:`соответствует ли содержимое расширению;`}),`
433
+ `,(0,c.jsx)(t.li,{children:`безопасно ли показывать файл;`}),`
434
+ `,(0,c.jsx)(t.li,{children:`не повреждён ли архив;`}),`
435
+ `,(0,c.jsx)(t.li,{children:`разрешён ли тип бизнес-правилами;`}),`
436
+ `,(0,c.jsx)(t.li,{children:`можно ли доверять MIME из внешнего источника.`}),`
437
+ `]}),`
438
+ `,(0,c.jsx)(t.h2,{id:`usebinaryfile`,children:(0,c.jsx)(t.code,{children:`useBinaryFile`})}),`
439
+ `,(0,c.jsx)(t.h3,{id:`сигнатура-2`,children:`Сигнатура`}),`
440
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function useBinaryFile(bin: string | undefined): {
441
+ data: {
442
+ blob: Blob;
443
+ mime: string;
444
+ } | null;
445
+ error: string | null;
446
+ };
447
+ `})}),`
448
+ `,(0,c.jsx)(t.p,{children:`Hook принимает только base64/base64 data URL. Он всегда вызывает:`}),`
449
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const mime = detectMimeType(undefined, bin);
450
+ const blob = binaryToBlob(bin, mime, true);
451
+ `})}),`
452
+ `,(0,c.jsx)(t.p,{children:`Filename передать нельзя, raw binary mode использовать нельзя.`}),`
453
+ `,(0,c.jsx)(t.h3,{id:`возвращаемое-состояние`,children:`Возвращаемое состояние`}),`
454
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Поле`}),(0,c.jsx)(t.th,{children:`Значение`}),(0,c.jsx)(t.th,{children:`Смысл`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`data`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`{ blob, mime }`})}),(0,c.jsx)(t.td,{children:`Декодирование завершилось успешно`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`data`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`null`})}),(0,c.jsx)(t.td,{children:`Нет результата либо произошла ошибка`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`error`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`string`})}),(0,c.jsx)(t.td,{children:`Строковое представление ошибки`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`error`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`null`})}),(0,c.jsx)(t.td,{children:`Ошибки нет`})]})]})]}),`
455
+ `,(0,c.jsx)(t.h3,{id:`lifecycle`,children:`Lifecycle`}),`
456
+ `,(0,c.jsx)(t.p,{children:`Преобразование выполняется после commit в React effect:`}),`
457
+ `,(0,c.jsxs)(t.ol,{children:[`
458
+ `,(0,c.jsxs)(t.li,{children:[`первый render возвращает `,(0,c.jsx)(t.code,{children:`{ data: null, error: null }`}),`;`]}),`
459
+ `,(0,c.jsxs)(t.li,{children:[`после commit effect обрабатывает `,(0,c.jsx)(t.code,{children:`bin`}),`;`]}),`
460
+ `,(0,c.jsxs)(t.li,{children:[`успех записывает `,(0,c.jsx)(t.code,{children:`{ blob, mime }`}),` и очищает ошибку;`]}),`
461
+ `,(0,c.jsxs)(t.li,{children:[`ошибка очищает `,(0,c.jsx)(t.code,{children:`data`}),` и записывает `,(0,c.jsx)(t.code,{children:`String(error)`}),`;`]}),`
462
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`undefined`}),` или пустая строка очищают оба поля.`]}),`
463
+ `]}),`
464
+ `,(0,c.jsx)(t.p,{children:`Пример последовательности:`}),`
465
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:(0,c.jsx)(t.code,{children:`bin`})}),(0,c.jsx)(t.th,{children:`Состояние после effect`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`undefined`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`{ data: null, error: null }`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`""`})}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`{ data: null, error: null }`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Корректный base64 PDF`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`{ data: { blob, mime: "application/pdf" }, error: null }`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Некорректный base64`}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`{ data: null, error: "Error: ..." }`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Строка из пробелов`}),(0,c.jsx)(t.td,{children:`Ошибка после удаления пробелов`})]})]})]}),`
466
+ `,(0,c.jsxs)(t.p,{children:[`У hook нет отдельного `,(0,c.jsx)(t.code,{children:`isLoading`}),`/`,(0,c.jsx)(t.code,{children:`isProcessing`}),`. На первом render `,(0,c.jsx)(t.code,{children:`data: null`}),` и `,(0,c.jsx)(t.code,{children:`error: null`}),` может означать как отсутствие входа, так и ещё не выполненный effect.`]}),`
467
+ `,(0,c.jsxs)(t.h3,{id:`смена-bin`,children:[`Смена `,(0,c.jsx)(t.code,{children:`bin`})]}),`
468
+ `,(0,c.jsxs)(t.p,{children:[`При смене одного непустого `,(0,c.jsx)(t.code,{children:`bin`}),` на другой предыдущие `,(0,c.jsx)(t.code,{children:`data`}),`/`,(0,c.jsx)(t.code,{children:`error`}),` могут оставаться видимыми до выполнения следующего effect. Hook не очищает состояние синхронно во время render.`]}),`
469
+ `,(0,c.jsx)(t.p,{children:`Если нельзя кратковременно показать предыдущий документ:`}),`
470
+ `,(0,c.jsxs)(t.ul,{children:[`
471
+ `,(0,c.jsx)(t.li,{children:`разместите hook в компоненте, который remount-ится по стабильному ID документа;`}),`
472
+ `,(0,c.jsx)(t.li,{children:`или выполните преобразование на явной границе загрузки;`}),`
473
+ `,(0,c.jsx)(t.li,{children:`или добавьте внешний state machine с identity результата.`}),`
474
+ `]}),`
475
+ `,(0,c.jsxs)(t.p,{children:[`Не используйте саму большую base64-строку как React `,(0,c.jsx)(t.code,{children:`key`}),`. Используйте безопасный стабильный ID документа:`]}),`
476
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`<BinaryDocument key={document.id} bin={document.content} />
477
+ `})}),`
478
+ `,(0,c.jsx)(t.h3,{id:`определение-mime-внутри-hook`,children:`Определение MIME внутри hook`}),`
479
+ `,(0,c.jsx)(t.p,{children:`Hook не знает filename. Приоритет будет таким:`}),`
480
+ `,(0,c.jsxs)(t.ol,{children:[`
481
+ `,(0,c.jsx)(t.li,{children:`MIME из data URL;`}),`
482
+ `,(0,c.jsx)(t.li,{children:`сигнатура;`}),`
483
+ `,(0,c.jsxs)(t.li,{children:[`fallback `,(0,c.jsx)(t.code,{children:`application/pdf`}),`.`]}),`
484
+ `]}),`
485
+ `,(0,c.jsxs)(t.p,{children:[`Обычный base64 текста без data URL и известной сигнатуры станет `,(0,c.jsx)(t.code,{children:`Blob`}),` с `,(0,c.jsx)(t.code,{children:`application/pdf`}),`:`]}),`
486
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`const { data } = useBinaryFile("SGVsbG8=");
487
+
488
+ // После effect:
489
+ // data?.mime === "application/pdf"
490
+ `})}),`
491
+ `,(0,c.jsxs)(t.p,{children:[`Если известны имя или MIME, вызывайте `,(0,c.jsx)(t.code,{children:`detectMimeType`}),` и `,(0,c.jsx)(t.code,{children:`binaryToBlob`}),` вручную.`]}),`
492
+ `,(0,c.jsx)(t.h3,{id:`ошибки-и-logging`,children:`Ошибки и logging`}),`
493
+ `,(0,c.jsx)(t.p,{children:`При ошибке hook:`}),`
494
+ `,(0,c.jsxs)(t.ol,{children:[`
495
+ `,(0,c.jsxs)(t.li,{children:[`вызывает внутренний `,(0,c.jsx)(t.code,{children:`logError(error)`}),`;`]}),`
496
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`logError`}),` пишет ошибку в `,(0,c.jsx)(t.code,{children:`console.error`}),`;`]}),`
497
+ `,(0,c.jsxs)(t.li,{children:[`возвращает `,(0,c.jsx)(t.code,{children:`error: String(error)`}),`;`]}),`
498
+ `,(0,c.jsxs)(t.li,{children:[`очищает `,(0,c.jsx)(t.code,{children:`data`}),`.`]}),`
499
+ `]}),`
500
+ `,(0,c.jsxs)(t.p,{children:[`Для обычного `,(0,c.jsx)(t.code,{children:`Error`}),` строка включает имя:`]}),`
501
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`Error: Некорректный формат base64
502
+ `})}),`
503
+ `,(0,c.jsxs)(t.p,{children:[`Не сравнивайте `,(0,c.jsx)(t.code,{children:`error`}),` с точным текстом browser `,(0,c.jsx)(t.code,{children:`DOMException`}),`: сообщение низкоуровневого `,(0,c.jsx)(t.code,{children:`atob`}),` может отличаться между средами.`]}),`
504
+ `,(0,c.jsx)(t.h3,{id:`базовое-использование`,children:`Базовое использование`}),`
505
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`import { useBinaryFile } from "@ryuzaki13/react-foundation-lib/binary";
506
+
507
+ type BinaryDocumentProps = {
508
+ readonly bin: string | undefined;
509
+ };
510
+
511
+ export function BinaryDocument(props: BinaryDocumentProps) {
512
+ const { data, error } = useBinaryFile(props.bin);
513
+
514
+ if (error) {
515
+ return <p role="alert">Не удалось подготовить документ</p>;
516
+ }
517
+
518
+ if (!props.bin) {
519
+ return <p>Документ не передан</p>;
520
+ }
521
+
522
+ if (!data) {
523
+ return <p>Подготовка документа…</p>;
524
+ }
525
+
526
+ return <DocumentViewer blob={data.blob} mime={data.mime} />;
527
+ }
528
+ `})}),`
529
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`DocumentViewer`}),` в примере — компонент host-приложения. Пакет `,(0,c.jsx)(t.code,{children:`binary`}),` его не предоставляет.`]}),`
530
+ `,(0,c.jsx)(t.h3,{id:`hook-не-создаёт-object-url`,children:`Hook не создаёт object URL`}),`
531
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`Blob`}),` можно передать компоненту, который принимает его напрямую. Если viewer требует строковый URL, вызывающий компонент отвечает за создание и cleanup.`]}),`
532
+ `,(0,c.jsxs)(t.p,{children:[`Корректная синхронизация с `,(0,c.jsx)(t.code,{children:`iframe`}),`:`]}),`
533
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`import { useEffect, useRef } from "react";
534
+
535
+ type BlobFrameProps = {
536
+ readonly blob: Blob;
537
+ readonly title: string;
538
+ };
539
+
540
+ export function BlobFrame(props: BlobFrameProps) {
541
+ const frameRef = useRef<HTMLIFrameElement>(null);
542
+
543
+ useEffect(() => {
544
+ const frame = frameRef.current;
545
+
546
+ if (!frame) return;
547
+
548
+ const objectUrl = URL.createObjectURL(props.blob);
549
+
550
+ frame.src = objectUrl;
551
+
552
+ return () => {
553
+ frame.removeAttribute("src");
554
+ URL.revokeObjectURL(objectUrl);
555
+ };
556
+ }, [props.blob]);
557
+
558
+ return <iframe ref={frameRef} title={props.title} />;
559
+ }
560
+ `})}),`
561
+ `,(0,c.jsx)(t.p,{children:`Effect синхронизирует React с внешним browser API и симметрично освобождает URL. Такой cleanup устойчив к повторному setup/cleanup в React Strict Mode.`}),`
562
+ `,(0,c.jsx)(t.h3,{id:`когда-hook-не-подходит`,children:`Когда hook не подходит`}),`
563
+ `,(0,c.jsxs)(t.p,{children:[`Не используйте `,(0,c.jsx)(t.code,{children:`useBinaryFile`}),`, если:`]}),`
564
+ `,(0,c.jsxs)(t.ul,{children:[`
565
+ `,(0,c.jsx)(t.li,{children:`код выполняется вне React;`}),`
566
+ `,(0,c.jsx)(t.li,{children:`MIME уже известен и не равен PDF fallback;`}),`
567
+ `,(0,c.jsx)(t.li,{children:`нужно учитывать filename;`}),`
568
+ `,(0,c.jsx)(t.li,{children:`данные являются raw binary string;`}),`
569
+ `,(0,c.jsx)(t.li,{children:`результат нужен немедленно в event handler;`}),`
570
+ `,(0,c.jsx)(t.li,{children:`нужен явный processing/error state machine;`}),`
571
+ `,(0,c.jsx)(t.li,{children:`преобразование большого payload нужно вынести с main thread.`}),`
572
+ `]}),`
573
+ `,(0,c.jsxs)(t.h2,{id:`работа-с-готовым-blob`,children:[`Работа с готовым `,(0,c.jsx)(t.code,{children:`Blob`})]}),`
574
+ `,(0,c.jsx)(t.h3,{id:`скачать-файл`,children:`Скачать файл`}),`
575
+ `,(0,c.jsxs)(t.p,{children:[`Используйте `,(0,c.jsx)(t.code,{children:`/dom`}),`:`]}),`
576
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { downloadFileFromBlob } from "@ryuzaki13/react-foundation-lib/dom";
577
+
578
+ downloadFileFromBlob(fileName, blob);
579
+ `})}),`
580
+ `,(0,c.jsx)(t.p,{children:`Helper создаёт object URL, запускает скачивание и освобождает URL.`}),`
581
+ `,(0,c.jsx)(t.h3,{id:`передать-в-viewer`,children:`Передать в viewer`}),`
582
+ `,(0,c.jsxs)(t.p,{children:[`Если viewer принимает `,(0,c.jsx)(t.code,{children:`Blob`}),`:`]}),`
583
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`<DocumentViewer blob={blob} mime={blob.type} />
584
+ `})}),`
585
+ `,(0,c.jsx)(t.p,{children:`Если viewer принимает URL, создайте object URL на его lifecycle boundary и обязательно выполните cleanup.`}),`
586
+ `,(0,c.jsx)(t.h3,{id:`прочитать-байты`,children:`Прочитать байты`}),`
587
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const buffer = await blob.arrayBuffer();
588
+ const bytes = new Uint8Array(buffer);
589
+
590
+ console.log(bytes.length);
591
+ `})}),`
592
+ `,(0,c.jsx)(t.h3,{id:`прочитать-текст`,children:`Прочитать текст`}),`
593
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const text = await blob.text();
594
+ `})}),`
595
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`blob.text()`}),` декодирует данные как текст. Для PDF, ZIP и изображений результат не имеет полезного смысла.`]}),`
596
+ `,(0,c.jsxs)(t.h3,{id:`отправить-через-formdata`,children:[`Отправить через `,(0,c.jsx)(t.code,{children:`FormData`})]}),`
597
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const formData = new FormData();
598
+
599
+ formData.append("file", blob, fileName);
600
+ `})}),`
601
+ `,(0,c.jsxs)(t.p,{children:[`Transport, authentication и обработка ответа не принадлежат модулю `,(0,c.jsx)(t.code,{children:`binary`}),`.`]}),`
602
+ `,(0,c.jsx)(t.h3,{id:`object-url-cleanup`,children:`Object URL cleanup`}),`
603
+ `,(0,c.jsx)(t.p,{children:`Неправильно:`}),`
604
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const src = URL.createObjectURL(blob);
605
+ image.src = src;
606
+
607
+ // URL никогда не освобождается.
608
+ `})}),`
609
+ `,(0,c.jsx)(t.p,{children:`Правильно:`}),`
610
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const src = URL.createObjectURL(blob);
611
+ image.src = src;
612
+
613
+ // Когда URL больше не нужен:
614
+ image.removeAttribute("src");
615
+ URL.revokeObjectURL(src);
616
+ `})}),`
617
+ `,(0,c.jsxs)(t.p,{children:[`Не вызывайте `,(0,c.jsx)(t.code,{children:`revokeObjectURL`}),` до того, как consumer закончил использовать URL.`]}),`
618
+ `,(0,c.jsx)(t.h2,{id:`готовые-рецепты`,children:`Готовые рецепты`}),`
619
+ `,(0,c.jsx)(t.h3,{id:`скачать-backend-файл-с-известным-именем`,children:`Скачать backend-файл с известным именем`}),`
620
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { binaryToBlob, detectMimeType } from "@ryuzaki13/react-foundation-lib/binary";
621
+ import { downloadFileFromBlob } from "@ryuzaki13/react-foundation-lib/dom";
622
+
623
+ function downloadFile(fileName: string, fileContent: string) {
624
+ const mime = detectMimeType(fileName, fileContent);
625
+ const blob = binaryToBlob(fileContent, mime);
626
+
627
+ downloadFileFromBlob(fileName, blob);
628
+ }
629
+ `})}),`
630
+ `,(0,c.jsx)(t.h3,{id:`создать-pdf-blob-при-известном-контракте-backend`,children:`Создать PDF Blob при известном контракте backend`}),`
631
+ `,(0,c.jsx)(t.p,{children:`Если backend-контракт гарантирует PDF, detection не нужен:`}),`
632
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = binaryToBlob(fileContent, "application/pdf");
633
+ `})}),`
634
+ `,(0,c.jsx)(t.p,{children:`Это надёжнее эвристики, если MIME гарантирован и проверяется владельцем transport/domain boundary.`}),`
635
+ `,(0,c.jsx)(t.h3,{id:`обработать-data-url`,children:`Обработать data URL`}),`
636
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`function dataUrlToBlob(dataUrl: string) {
637
+ const mime = detectMimeType(undefined, dataUrl);
638
+
639
+ return binaryToBlob(dataUrl, mime);
640
+ }
641
+ `})}),`
642
+ `,(0,c.jsx)(t.h3,{id:`обработать-url-safe-base64`,children:`Обработать URL-safe base64`}),`
643
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = binaryToBlob(urlSafePayload, "application/octet-stream");
644
+ `})}),`
645
+ `,(0,c.jsx)(t.p,{children:`Дополнительных замен в consumer-коде не требуется.`}),`
646
+ `,(0,c.jsx)(t.h3,{id:`обработать-raw-binary-string`,children:`Обработать raw binary string`}),`
647
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = binaryToBlob(rawBinaryString, "application/pdf", false);
648
+ `})}),`
649
+ `,(0,c.jsx)(t.p,{children:`Используйте только когда upstream явно гарантирует raw binary string.`}),`
650
+ `,(0,c.jsx)(t.h3,{id:`показать-base64-документ-в-react`,children:`Показать base64-документ в React`}),`
651
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-tsx`,children:`function DocumentPanel(props: { readonly documentId: string; readonly base64: string | undefined }) {
652
+ return <BinaryDocument key={props.documentId} bin={props.base64} />;
653
+ }
654
+ `})}),`
655
+ `,(0,c.jsx)(t.h3,{id:`отладочно-проверить-первые-байты`,children:`Отладочно проверить первые байты`}),`
656
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = binaryToBlob(payload, "application/octet-stream");
657
+ const bytes = new Uint8Array(await blob.arrayBuffer());
658
+
659
+ console.log([...bytes.slice(0, 8)]);
660
+ `})}),`
661
+ `,(0,c.jsx)(t.p,{children:`Не оставляйте logging бинарного содержимого в production-коде.`}),`
662
+ `,(0,c.jsx)(t.h2,{id:`ошибки-и-диагностика`,children:`Ошибки и диагностика`}),`
663
+ `,(0,c.jsx)(t.h3,{id:`не-переданы-бинарные-данные`,children:`«Не переданы бинарные данные»`}),`
664
+ `,(0,c.jsx)(t.p,{children:`Причина:`}),`
665
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`binaryToBlob("");
666
+ `})}),`
667
+ `,(0,c.jsx)(t.p,{children:`Решение: различайте отсутствие payload и корректное содержимое до вызова функции.`}),`
668
+ `,(0,c.jsx)(t.h3,{id:`после-преобразования-не-осталось-данных`,children:`«После преобразования не осталось данных»`}),`
669
+ `,(0,c.jsx)(t.p,{children:`Причины:`}),`
670
+ `,(0,c.jsxs)(t.ul,{children:[`
671
+ `,(0,c.jsx)(t.li,{children:`data URL имеет пустой payload;`}),`
672
+ `,(0,c.jsx)(t.li,{children:`base64 состоит только из пробелов;`}),`
673
+ `,(0,c.jsx)(t.li,{children:`после удаления whitespace не осталось символов.`}),`
674
+ `]}),`
675
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`binaryToBlob("data:text/plain;base64,");
676
+ `})}),`
677
+ `,(0,c.jsx)(t.h3,{id:`некорректный-формат-base64`,children:`«Некорректный формат base64»`}),`
678
+ `,(0,c.jsx)(t.p,{children:`Причины:`}),`
679
+ `,(0,c.jsxs)(t.ul,{children:[`
680
+ `,(0,c.jsx)(t.li,{children:`присутствуют недопустимые символы;`}),`
681
+ `,(0,c.jsx)(t.li,{children:`строка имеет невозможную длину;`}),`
682
+ `,(0,c.jsx)(t.li,{children:`передан обычный текст вместо base64;`}),`
683
+ `,(0,c.jsx)(t.li,{children:`передан percent-encoded data URL;`}),`
684
+ `,(0,c.jsx)(t.li,{children:`payload был повреждён transport-слоем.`}),`
685
+ `]}),`
686
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`binaryToBlob("not valid *");
687
+ `})}),`
688
+ `,(0,c.jsxs)(t.h3,{id:`base64-из-queryform-потерял-`,children:[`Base64 из query/form потерял `,(0,c.jsx)(t.code,{children:`+`})]}),`
689
+ `,(0,c.jsxs)(t.p,{children:[`В `,(0,c.jsx)(t.code,{children:`application/x-www-form-urlencoded`}),` символ `,(0,c.jsx)(t.code,{children:`+`}),` может интерпретироваться как пробел. Модуль удалит пробел и не сможет восстановить потерянный байт.`]}),`
690
+ `,(0,c.jsx)(t.p,{children:`Передавайте base64:`}),`
691
+ `,(0,c.jsxs)(t.ul,{children:[`
692
+ `,(0,c.jsx)(t.li,{children:`в JSON body;`}),`
693
+ `,(0,c.jsx)(t.li,{children:`как URL-safe base64;`}),`
694
+ `,(0,c.jsx)(t.li,{children:`или с корректным percent-encoding.`}),`
695
+ `]}),`
696
+ `,(0,c.jsxs)(t.h3,{id:`blobtype-равен-applicationoctet-stream`,children:[(0,c.jsx)(t.code,{children:`Blob.type`}),` равен `,(0,c.jsx)(t.code,{children:`application/octet-stream`})]}),`
697
+ `,(0,c.jsxs)(t.p,{children:[`Причина: `,(0,c.jsx)(t.code,{children:`binaryToBlob`}),` не выполняет detection и не использует MIME data URL автоматически.`]}),`
698
+ `,(0,c.jsx)(t.p,{children:`Решение:`}),`
699
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const mime = detectMimeType(fileName, payload);
700
+ const blob = binaryToBlob(payload, mime);
701
+ `})}),`
702
+ `,(0,c.jsx)(t.h3,{id:`hook-определил-текст-как-pdf`,children:`Hook определил текст как PDF`}),`
703
+ `,(0,c.jsxs)(t.p,{children:[`Причина: `,(0,c.jsx)(t.code,{children:`useBinaryFile`}),` не получает filename, сигнатура текста неизвестна, поэтому применяется PDF fallback.`]}),`
704
+ `,(0,c.jsx)(t.p,{children:`Решения:`}),`
705
+ `,(0,c.jsxs)(t.ul,{children:[`
706
+ `,(0,c.jsx)(t.li,{children:`передать data URL с MIME;`}),`
707
+ `,(0,c.jsx)(t.li,{children:`вызвать функции вручную с известным MIME;`}),`
708
+ `,(0,c.jsx)(t.li,{children:`не использовать hook для этого контракта.`}),`
709
+ `]}),`
710
+ `,(0,c.jsx)(t.h3,{id:`mime-не-совпал-с-содержимым`,children:`MIME не совпал с содержимым`}),`
711
+ `,(0,c.jsx)(t.p,{children:`Проверьте приоритет:`}),`
712
+ `,(0,c.jsxs)(t.ol,{children:[`
713
+ `,(0,c.jsx)(t.li,{children:`filename;`}),`
714
+ `,(0,c.jsx)(t.li,{children:`data URL;`}),`
715
+ `,(0,c.jsx)(t.li,{children:`signature;`}),`
716
+ `,(0,c.jsx)(t.li,{children:`PDF fallback.`}),`
717
+ `]}),`
718
+ `,(0,c.jsx)(t.p,{children:`Известное расширение filename всегда выигрывает, даже если данные заявляют другой тип.`}),`
719
+ `,(0,c.jsx)(t.h3,{id:`data-url-не-распознан`,children:`Data URL не распознан`}),`
720
+ `,(0,c.jsx)(t.p,{children:`Поддерживается форма:`}),`
721
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`data:<mime>[;parameters];base64,<payload>
722
+ `})}),`
723
+ `,(0,c.jsx)(t.p,{children:`Не поддерживается:`}),`
724
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-text`,children:`data:<mime>,<percent-encoded-payload>
725
+ `})}),`
726
+ `,(0,c.jsxs)(t.h3,{id:`ошибка-появляется-в-consoleerror`,children:[`Ошибка появляется в `,(0,c.jsx)(t.code,{children:`console.error`})]}),`
727
+ `,(0,c.jsxs)(t.p,{children:[`Это текущее поведение `,(0,c.jsx)(t.code,{children:`useBinaryFile`}),`: hook логирует пойманную ошибку перед записью `,(0,c.jsx)(t.code,{children:`error`}),` state. Для ручного `,(0,c.jsx)(t.code,{children:`binaryToBlob`}),` logging не выполняется.`]}),`
728
+ `,(0,c.jsx)(t.h3,{id:`object-url-перестал-работать`,children:`Object URL перестал работать`}),`
729
+ `,(0,c.jsx)(t.p,{children:`Проверьте, что:`}),`
730
+ `,(0,c.jsxs)(t.ul,{children:[`
731
+ `,(0,c.jsx)(t.li,{children:`URL не был освобождён слишком рано;`}),`
732
+ `,(0,c.jsx)(t.li,{children:`cleanup старого URL не затронул новый URL;`}),`
733
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`Blob`}),` ещё соответствует текущему документу;`]}),`
734
+ `,(0,c.jsxs)(t.li,{children:[`browser CSP/viewer разрешает `,(0,c.jsx)(t.code,{children:`blob:`}),` source.`]}),`
735
+ `]}),`
736
+ `,(0,c.jsx)(t.h2,{id:`безопасность`,children:`Безопасность`}),`
737
+ `,(0,c.jsx)(t.h3,{id:`mime-нельзя-использовать-как-проверку-безопасности`,children:`MIME нельзя использовать как проверку безопасности`}),`
738
+ `,(0,c.jsx)(t.p,{children:`Следующие источники контролируемы внешними данными:`}),`
739
+ `,(0,c.jsxs)(t.ul,{children:[`
740
+ `,(0,c.jsx)(t.li,{children:`filename;`}),`
741
+ `,(0,c.jsx)(t.li,{children:`MIME data URL;`}),`
742
+ `,(0,c.jsx)(t.li,{children:`первые байты payload.`}),`
743
+ `]}),`
744
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`detectMimeType`}),` не гарантирует, что файл безопасен или соответствует типу.`]}),`
745
+ `,(0,c.jsx)(t.h3,{id:`активное-содержимое`,children:`Активное содержимое`}),`
746
+ `,(0,c.jsx)(t.p,{children:`SVG, HTML, XML и некоторые PDF могут содержать активные или внешние ссылки. Не вставляйте непроверенное содержимое напрямую в DOM.`}),`
747
+ `,(0,c.jsx)(t.p,{children:`Для недоверенных файлов:`}),`
748
+ `,(0,c.jsxs)(t.ul,{children:[`
749
+ `,(0,c.jsx)(t.li,{children:`используйте безопасный viewer;`}),`
750
+ `,(0,c.jsx)(t.li,{children:`учитывайте sandbox/CSP;`}),`
751
+ `,(0,c.jsx)(t.li,{children:`запрещайте опасные типы на доверенной server boundary;`}),`
752
+ `,(0,c.jsx)(t.li,{children:`не полагайтесь только на расширение;`}),`
753
+ `,(0,c.jsx)(t.li,{children:`не выполняйте содержимое как script/module.`}),`
754
+ `]}),`
755
+ `,(0,c.jsx)(t.h3,{id:`ограничивайте-размер`,children:`Ограничивайте размер`}),`
756
+ `,(0,c.jsx)(t.p,{children:`Перед декодированием проверяйте допустимый размер ответа на transport/domain boundary. Base64 и несколько промежуточных копий могут значительно увеличить потребление памяти.`}),`
757
+ `,(0,c.jsx)(t.h3,{id:`не-логируйте-payload`,children:`Не логируйте payload`}),`
758
+ `,(0,c.jsx)(t.p,{children:`Base64 может содержать:`}),`
759
+ `,(0,c.jsxs)(t.ul,{children:[`
760
+ `,(0,c.jsx)(t.li,{children:`персональные данные;`}),`
761
+ `,(0,c.jsx)(t.li,{children:`договоры и документы;`}),`
762
+ `,(0,c.jsx)(t.li,{children:`изображения;`}),`
763
+ `,(0,c.jsx)(t.li,{children:`токены, если upstream ошибочно включил их;`}),`
764
+ `,(0,c.jsx)(t.li,{children:`другие чувствительные сведения.`}),`
765
+ `]}),`
766
+ `,(0,c.jsx)(t.p,{children:`В diagnostics передавайте безопасные metadata: источник, ожидаемый тип, размер строки и технический код ошибки — без самого содержимого.`}),`
767
+ `,(0,c.jsx)(t.h3,{id:`не-доверяйте-filename`,children:`Не доверяйте filename`}),`
768
+ `,(0,c.jsx)(t.p,{children:`Filename может содержать нежелательные символы или обманное расширение. Санитизация имени и бизнес-политика разрешённых форматов принадлежат boundary, которая принимает внешний файл.`}),`
769
+ `,(0,c.jsx)(t.h2,{id:`производительность-и-память`,children:`Производительность и память`}),`
770
+ `,(0,c.jsx)(t.h3,{id:`синхронное-декодирование`,children:`Синхронное декодирование`}),`
771
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`binaryToBlob`}),` синхронно:`]}),`
772
+ `,(0,c.jsxs)(t.ul,{children:[`
773
+ `,(0,c.jsx)(t.li,{children:`нормализует всю строку;`}),`
774
+ `,(0,c.jsxs)(t.li,{children:[`вызывает `,(0,c.jsx)(t.code,{children:`atob`}),`;`]}),`
775
+ `,(0,c.jsxs)(t.li,{children:[`создаёт `,(0,c.jsx)(t.code,{children:`Uint8Array`}),`;`]}),`
776
+ `,(0,c.jsxs)(t.li,{children:[`создаёт отдельный `,(0,c.jsx)(t.code,{children:`ArrayBuffer`}),`;`]}),`
777
+ `,(0,c.jsxs)(t.li,{children:[`создаёт `,(0,c.jsx)(t.code,{children:`Blob`}),`.`]}),`
778
+ `]}),`
779
+ `,(0,c.jsx)(t.p,{children:`Большой payload может заблокировать main thread и временно существовать в нескольких представлениях одновременно.`}),`
780
+ `,(0,c.jsx)(t.h3,{id:`base64-больше-исходных-байтов`,children:`Base64 больше исходных байтов`}),`
781
+ `,(0,c.jsx)(t.p,{children:`Base64 обычно примерно на треть больше исходного binary payload, не считая префикса data URL и JavaScript string storage.`}),`
782
+ `,(0,c.jsxs)(t.h3,{id:`detectmimetype-декодирует-только-начало`,children:[(0,c.jsx)(t.code,{children:`detectMimeType`}),` декодирует только начало`]}),`
783
+ `,(0,c.jsxs)(t.p,{children:[`Signature detection декодирует ограниченное начало base64, поэтому дешевле полного декодирования. При этом распознавание data URL выполняется регулярным выражением над входной строкой и может просканировать весь payload. Последующий `,(0,c.jsx)(t.code,{children:`binaryToBlob`}),` в любом случае обрабатывает полный payload.`]}),`
784
+ `,(0,c.jsx)(t.h3,{id:`рекомендации`,children:`Рекомендации`}),`
785
+ `,(0,c.jsxs)(t.ul,{children:[`
786
+ `,(0,c.jsx)(t.li,{children:`ограничивайте размер на backend и transport boundary;`}),`
787
+ `,(0,c.jsx)(t.li,{children:`не декодируйте один payload несколько раз без причины;`}),`
788
+ `,(0,c.jsxs)(t.li,{children:[`не храните одновременно много больших base64-строк и `,(0,c.jsx)(t.code,{children:`Blob`}),`;`]}),`
789
+ `,(0,c.jsx)(t.li,{children:`освобождайте object URL;`}),`
790
+ `,(0,c.jsx)(t.li,{children:`для действительно больших файлов предпочитайте streaming/download endpoint;`}),`
791
+ `,(0,c.jsx)(t.li,{children:`не выполняйте тяжёлое декодирование каждого render;`}),`
792
+ `,(0,c.jsxs)(t.li,{children:[`не используйте `,(0,c.jsx)(t.code,{children:`useBinaryFile`}),` как cache больших backend-файлов.`]}),`
793
+ `]}),`
794
+ `,(0,c.jsx)(t.h3,{id:`сложность`,children:`Сложность`}),`
795
+ `,(0,c.jsxs)(t.p,{children:[`Для payload длины `,(0,c.jsx)(t.code,{children:`n`}),`:`]}),`
796
+ `,(0,c.jsxs)(t.ul,{children:[`
797
+ `,(0,c.jsxs)(t.li,{children:[`время `,(0,c.jsx)(t.code,{children:`binaryToBlob`}),` — `,(0,c.jsx)(t.code,{children:`O(n)`}),`;`]}),`
798
+ `,(0,c.jsxs)(t.li,{children:[`дополнительная память — `,(0,c.jsx)(t.code,{children:`O(n)`}),`;`]}),`
799
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`detectMimeType`}),` — `,(0,c.jsx)(t.code,{children:`O(n)`}),` в худшем случае из-за разбора data URL, хотя для signature декодируется только ограниченный header.`]}),`
800
+ `]}),`
801
+ `,(0,c.jsx)(t.h2,{id:`тестирование`,children:`Тестирование`}),`
802
+ `,(0,c.jsx)(t.h3,{id:`тесты-consumer-кода`,children:`Тесты consumer-кода`}),`
803
+ `,(0,c.jsx)(t.p,{children:`Проверяйте:`}),`
804
+ `,(0,c.jsxs)(t.ul,{children:[`
805
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`blob.type`}),`;`]}),`
806
+ `,(0,c.jsxs)(t.li,{children:[(0,c.jsx)(t.code,{children:`blob.size`}),`;`]}),`
807
+ `,(0,c.jsx)(t.li,{children:`текст для текстового fixture;`}),`
808
+ `,(0,c.jsxs)(t.li,{children:[`байты через `,(0,c.jsx)(t.code,{children:`arrayBuffer()`}),`;`]}),`
809
+ `,(0,c.jsx)(t.li,{children:`ожидаемые ошибки;`}),`
810
+ `,(0,c.jsx)(t.li,{children:`cleanup object URL в UI boundary.`}),`
811
+ `]}),`
812
+ `,(0,c.jsx)(t.p,{children:`Пример:`}),`
813
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { describe, expect, it } from "vitest";
814
+
815
+ import { binaryToBlob, detectMimeType } from "@ryuzaki13/react-foundation-lib/binary";
816
+
817
+ describe("binary document", () => {
818
+ it("создаёт текстовый Blob", async () => {
819
+ const blob = binaryToBlob("SGVsbG8=", "text/plain");
820
+
821
+ expect(blob.type).toBe("text/plain");
822
+ expect(await blob.text()).toBe("Hello");
823
+ });
824
+
825
+ it("определяет PDF по имени", () => {
826
+ expect(detectMimeType("report.pdf")).toBe("application/pdf");
827
+ });
828
+ });
829
+ `})}),`
830
+ `,(0,c.jsxs)(t.p,{children:[`Тестовая среда должна предоставлять `,(0,c.jsx)(t.code,{children:`Blob`}),`, `,(0,c.jsx)(t.code,{children:`atob`}),` и при UI-тестах React DOM. В пакете pure-функции проверяются в `,(0,c.jsx)(t.code,{children:`jsdom`}),`.`]}),`
831
+ `,(0,c.jsx)(t.h3,{id:`узкий-тест-пакета`,children:`Узкий тест пакета`}),`
832
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-bash`,children:`npm run test -- src/binary/binaryToBlob.test.ts
833
+ `})}),`
834
+ `,(0,c.jsx)(t.h2,{id:`краткий-справочник-api`,children:`Краткий справочник API`}),`
835
+ `,(0,c.jsx)(t.p,{children:`Полный импорт:`}),`
836
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`import { binaryToBlob, detectMimeType, useBinaryFile } from "@ryuzaki13/react-foundation-lib/binary";
837
+ `})}),`
838
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`API`}),(0,c.jsx)(t.th,{children:`Вход`}),(0,c.jsx)(t.th,{children:`Результат`}),(0,c.jsx)(t.th,{children:`Ошибка`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`binaryToBlob`})}),(0,c.jsx)(t.td,{children:`Строка, MIME, base64/raw флаг`}),(0,c.jsxs)(t.td,{children:[`Непустой `,(0,c.jsx)(t.code,{children:`Blob`})]}),(0,c.jsxs)(t.td,{children:[`Выбрасывает `,(0,c.jsx)(t.code,{children:`Error`}),`/browser decode error`]})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`detectMimeType`})}),(0,c.jsx)(t.td,{children:`Filename и/или base64/data URL`}),(0,c.jsx)(t.td,{children:`MIME string`}),(0,c.jsx)(t.td,{children:`Не выбрасывает; fallback PDF`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`useBinaryFile`})}),(0,c.jsxs)(t.td,{children:[`Base64/data URL или `,(0,c.jsx)(t.code,{children:`undefined`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`{ data, error }`})}),(0,c.jsx)(t.td,{children:`Логирует и возвращает строку ошибки`})]})]})]}),`
839
+ `,(0,c.jsx)(t.h3,{id:`defaults`,children:`Defaults`}),`
840
+ `,(0,c.jsxs)(t.table,{children:[(0,c.jsx)(t.thead,{children:(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.th,{children:`Контракт`}),(0,c.jsx)(t.th,{children:`Значение`})]})}),(0,c.jsxs)(t.tbody,{children:[(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`binaryToBlob`}),` MIME`]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/octet-stream`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`binaryToBlob`}),` input mode`]}),(0,c.jsx)(t.td,{children:`base64`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`detectMimeType`}),` fallback`]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`application/pdf`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`useBinaryFile`}),` initial `,(0,c.jsx)(t.code,{children:`data`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`null`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`useBinaryFile`}),` initial `,(0,c.jsx)(t.code,{children:`error`})]}),(0,c.jsx)(t.td,{children:(0,c.jsx)(t.code,{children:`null`})})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsxs)(t.td,{children:[(0,c.jsx)(t.code,{children:`useBinaryFile`}),` raw binary support`]}),(0,c.jsx)(t.td,{children:`Нет`})]}),(0,c.jsxs)(t.tr,{children:[(0,c.jsx)(t.td,{children:`Автоматическое создание object URL`}),(0,c.jsx)(t.td,{children:`Нет`})]})]})]}),`
841
+ `,(0,c.jsx)(t.h2,{id:`вопросы-и-ответы`,children:`Вопросы и ответы`}),`
842
+ `,(0,c.jsx)(t.h3,{id:`base64--это-шифрование`,children:`Base64 — это шифрование?`}),`
843
+ `,(0,c.jsx)(t.p,{children:`Нет. Это текстовое кодирование байтов. Оно не обеспечивает секретность, целостность или подлинность.`}),`
844
+ `,(0,c.jsxs)(t.h3,{id:`почему-binarytoblob-не-определяет-mime-сам`,children:[`Почему `,(0,c.jsx)(t.code,{children:`binaryToBlob`}),` не определяет MIME сам?`]}),`
845
+ `,(0,c.jsxs)(t.p,{children:[`Преобразование байтов и выбор MIME являются разными ответственностями. Вызывающий код может знать MIME точнее любой эвристики. Для предположения существует отдельная `,(0,c.jsx)(t.code,{children:`detectMimeType`}),`.`]}),`
846
+ `,(0,c.jsxs)(t.h3,{id:`почему-fallback-у-binarytoblob-и-detectmimetype-разный`,children:[`Почему fallback у `,(0,c.jsx)(t.code,{children:`binaryToBlob`}),` и `,(0,c.jsx)(t.code,{children:`detectMimeType`}),` разный?`]}),`
847
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`binaryToBlob`}),` без информации создаёт нейтральный `,(0,c.jsx)(t.code,{children:`application/octet-stream`}),`. `,(0,c.jsx)(t.code,{children:`detectMimeType`}),` ориентирован на документный контур и возвращает `,(0,c.jsx)(t.code,{children:`application/pdf`}),`, если эвристики не сработали.`]}),`
848
+ `,(0,c.jsxs)(t.h3,{id:`почему-mime-data-url-не-попал-в-blob`,children:[`Почему MIME data URL не попал в `,(0,c.jsx)(t.code,{children:`Blob`}),`?`]}),`
849
+ `,(0,c.jsxs)(t.p,{children:[(0,c.jsx)(t.code,{children:`binaryToBlob`}),` использует data URL только для извлечения base64 payload. Передайте MIME вторым аргументом:`]}),`
850
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const mime = detectMimeType(undefined, dataUrl);
851
+ const blob = binaryToBlob(dataUrl, mime);
852
+ `})}),`
853
+ `,(0,c.jsx)(t.h3,{id:`почему-docx-определился-как-zip`,children:`Почему DOCX определился как ZIP?`}),`
854
+ `,(0,c.jsxs)(t.p,{children:[`DOCX, XLSX и PPTX технически являются ZIP-контейнерами. Без filename короткая signature видит только `,(0,c.jsx)(t.code,{children:`PK`}),`. Передавайте корректное имя или известный MIME.`]}),`
855
+ `,(0,c.jsx)(t.h3,{id:`почему-неизвестный-файл-определился-как-pdf`,children:`Почему неизвестный файл определился как PDF?`}),`
856
+ `,(0,c.jsxs)(t.p,{children:[`Это fallback `,(0,c.jsx)(t.code,{children:`detectMimeType`}),`. Он не доказывает, что файл является PDF.`]}),`
857
+ `,(0,c.jsxs)(t.h3,{id:`можно-ли-передать-uint8array`,children:[`Можно ли передать `,(0,c.jsx)(t.code,{children:`Uint8Array`}),`?`]}),`
858
+ `,(0,c.jsxs)(t.p,{children:[`Нет, публичный API принимает строку. Для готовых байтов создайте `,(0,c.jsx)(t.code,{children:`Blob`}),` напрямую:`]}),`
859
+ `,(0,c.jsx)(t.pre,{children:(0,c.jsx)(t.code,{className:`language-ts`,children:`const blob = new Blob([bytes], { type: mime });
860
+ `})}),`
861
+ `,(0,c.jsx)(t.h3,{id:`можно-ли-передать-обычный-текст`,children:`Можно ли передать обычный текст?`}),`
862
+ `,(0,c.jsxs)(t.p,{children:[`Если текст уже корректно закодирован в base64 — да. Raw mode не является UTF-8 encoder. Для обычного Unicode-текста используйте `,(0,c.jsx)(t.code,{children:`TextEncoder`}),`.`]}),`
863
+ `,(0,c.jsxs)(t.h3,{id:`нужно-ли-вручную-освобождать-blob`,children:[`Нужно ли вручную освобождать `,(0,c.jsx)(t.code,{children:`Blob`}),`?`]}),`
864
+ `,(0,c.jsxs)(t.p,{children:[`Нет. Нужно освобождать object URL, созданный через `,(0,c.jsx)(t.code,{children:`URL.createObjectURL(blob)`}),`.`]}),`
865
+ `,(0,c.jsxs)(t.h3,{id:`создаёт-ли-usebinaryfile-object-url`,children:[`Создаёт ли `,(0,c.jsx)(t.code,{children:`useBinaryFile`}),` object URL?`]}),`
866
+ `,(0,c.jsxs)(t.p,{children:[`Нет. Hook возвращает только `,(0,c.jsx)(t.code,{children:`Blob`}),` и MIME.`]}),`
867
+ `,(0,c.jsxs)(t.h3,{id:`можно-ли-использовать-usebinaryfile-вне-react-компонента`,children:[`Можно ли использовать `,(0,c.jsx)(t.code,{children:`useBinaryFile`}),` вне React-компонента?`]}),`
868
+ `,(0,c.jsxs)(t.p,{children:[`Нет. Это React hook, к нему применяются Rules of Hooks. Для обычной функции используйте `,(0,c.jsx)(t.code,{children:`binaryToBlob`}),` и `,(0,c.jsx)(t.code,{children:`detectMimeType`}),`.`]}),`
869
+ `,(0,c.jsx)(t.h3,{id:`почему-entrypoint-требует-react-если-нужна-только-pure-функция`,children:`Почему entrypoint требует React, если нужна только pure-функция?`}),`
870
+ `,(0,c.jsxs)(t.p,{children:[`Текущий `,(0,c.jsx)(t.code,{children:`/binary`}),` entrypoint также экспортирует `,(0,c.jsx)(t.code,{children:`useBinaryFile`}),`, а собранный ESM-модуль импортирует React. Поэтому React должен быть доступен при разрешении entrypoint.`]}),`
871
+ `,(0,c.jsxs)(t.h3,{id:`валидирует-ли-detectmimetype-файл`,children:[`Валидирует ли `,(0,c.jsx)(t.code,{children:`detectMimeType`}),` файл?`]}),`
872
+ `,(0,c.jsx)(t.p,{children:`Нет. Это только эвристический выбор MIME.`}),`
873
+ `,(0,c.jsx)(t.h3,{id:`можно-ли-использовать-результат-для-проверки-разрешённого-типа`,children:`Можно ли использовать результат для проверки разрешённого типа?`}),`
874
+ `,(0,c.jsx)(t.p,{children:`Не как единственную проверку. Политику разрешённых форматов и проверку недоверенного содержимого выполняйте на доверенной boundary.`}),`
875
+ `,(0,c.jsx)(t.h3,{id:`что-выбрать-data-url-или-object-url`,children:`Что выбрать: data URL или object URL?`}),`
876
+ `,(0,c.jsxs)(t.p,{children:[`Data URL содержит данные внутри строки и часто приходит извне. Object URL является временной ссылкой браузера на уже созданный `,(0,c.jsx)(t.code,{children:`Blob`}),`. Для отображения большого `,(0,c.jsx)(t.code,{children:`Blob`}),` обычно удобнее object URL с обязательным cleanup.`]})]})}function s(e={}){let{wrapper:t}={...n(),...e.components};return t?(0,c.jsx)(t,{...e,children:(0,c.jsx)(o,{...e})}):o(e)}var c;function l(){return(l=e((()=>{c=t(),r(),a()})))()}l();export{s as default};