{"id":452540,"date":"2025-03-21T09:00:49","date_gmt":"2025-03-21T09:00:49","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=452540"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=452540","title":{"rendered":"<span>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043b\u044f React-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0432 2025 \u0433\u043e\u0434\u0443: \u043d\u0430 \u0447\u0442\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c5b\/37f\/fc6\/c5b37ffc65638e97dae8617c5683a0a6.png\" width=\"1920\" height=\"1080\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c5b\/37f\/fc6\/c5b37ffc65638e97dae8617c5683a0a6.png\"\/><\/figure>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440\u0447\u0430\u043d\u0435! \u042d\u0442\u043e \u041b\u0435\u0448\u0430 \u0416\u0438\u0440\u044f\u043a\u043e\u0432, \u0442\u0435\u0445\u043b\u0438\u0434 backend-\u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u0438\u0442\u0440\u0438\u043d\u044b KION. \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437 \u044f \u043f\u0438\u0441\u0430\u043b <a href=\"https:\/\/habr.com\/ru\/companies\/ru_mts\/articles\/884376\/\">\u043e \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 Python<\/a>, \u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0442 \u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043d\u0430 React. \u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0441\u0442\u043e\u0438\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u0432\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0432 2025 \u0433\u043e\u0434\u0443, \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043f\u043b\u044e\u0441\u044b \u0438 \u043c\u0438\u043d\u0443\u0441\u044b \u043a\u0430\u0436\u0434\u043e\u0439, \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 GitHub \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u0430\u0447\u043d\u0435\u043c!<\/p>\n<h2>Tremor<\/h2>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/d93\/5ce\/852\/d935ce852065244cd2c9ab602f715528.jpg\" width=\"1027\" height=\"172\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d93\/5ce\/852\/d935ce852065244cd2c9ab602f715528.jpg\" data-blurred=\"true\"\/><\/figure>\n<p><a href=\"https:\/\/tremor.so\/\">Tremor<\/a> \u2014 UI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u0432 \u0438 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0432 React. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0437\u0430\u0442\u043e\u0447\u0435\u043d\u043d\u044b\u0445 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, Tremor \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 UI-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b: \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438, \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043a\u043d\u043e\u043f\u043a\u0438, \u0433\u0440\u0430\u0444\u0438\u043a\u0438, \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043d\u0430 Tailwind CSS (\u043e\u0431 \u044d\u0442\u043e\u043c \u0432 \u0431\u043b\u043e\u0433\u0435 <a href=\"https:\/\/habr.com\/ru\/companies\/ru_mts\/articles\/860534\/\">\u043f\u0438\u0441\u0430\u043b<\/a> \u043a\u043e\u043b\u043b\u0435\u0433\u0430), \u0442\u0430\u043a \u0447\u0442\u043e \u043e\u043d\u0430 \u0443\u0434\u043e\u0431\u043d\u0430 \u0434\u043b\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0438\u0434\u0435\u044f Tremor \u2014 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u0432, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0445\u043e\u0440\u043e\u0448\u043e \u0441\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0438 \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u0437\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0443 \u0441 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043c\u0435\u0442\u0440\u0438\u043a\u043e\u0439 \u0438\u043b\u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443 \u0438\u0437 Recharts, Nivo \u0438\u043b\u0438 ECharts. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043c\u043d\u0430\u044f \u0438 \u0441\u0432\u0435\u0442\u043b\u0430\u044f \u0442\u0435\u043c\u044b, \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430 \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u044f \u043a \u0440\u0430\u0437\u043d\u044b\u043c \u044d\u043a\u0440\u0430\u043d\u0430\u043c.<\/p>\n<p><strong>\u041f\u043b\u044e\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0433\u043e\u0442\u043e\u0432\u044b\u0435 UI-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043b\u0435\u0433\u043a\u0430\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Recharts, Nivo \u0438 ECharts;<\/p>\n<\/li>\n<li>\n<p>\u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f Tailwind CSS.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041c\u0438\u043d\u0443\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u0430\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0432 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u0441 \u0447\u0438\u0441\u0442\u044b\u043c\u0438 UI-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430\u043c\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0438 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/tremorlabs\/tremor\"><strong>GitHub<\/strong><\/a>:<\/p>\n<ul>\n<li>\n<p>\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0432\u0435\u0437\u0434: 2,1 \u0442\u044b\u0441.;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 Issues: 11;<\/p>\n<\/li>\n<li>\n<p>\u0433\u043e\u0434 \u0440\u0435\u043b\u0438\u0437\u0430: 2024;<\/p>\n<\/li>\n<li>\n<p>Merge Requests (MRs): \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0434\u0430\u0448\u0431\u043e\u0440\u0434 \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0443\u0441\u0438\u043b\u0438\u044f\u043c\u0438, \u043d\u043e \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u0435 UI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<\/p>\n<h3>\u0415\u0449\u0435 \u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u043e\u0440\u043e\u043d\u0430\u0445<\/h3>\n<p>Tremor \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432: \u0433\u0440\u0430\u0444\u0438\u043a\u0438 (Area Chart, Bar Chart, Donut Chart, Progress Bar), \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 (Calendar, Checkbox, Date Picker, Radio Card Group) \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 UI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b (Badge, Button, Dialog, Table).<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 (<a href=\"https:\/\/tremor.so\/docs\/ui\/button\">Button<\/a>). \u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Tremor \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d: Ctrl + C, Ctrl + V \u2014 \u0438 \u0432\u043f\u0435\u0440\u0435\u0434!<\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"python\">npm install @radix-ui\/react-slot tailwind-variants @remixicon\/react<\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u0434 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b. \u0412\u0430\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u044b:<\/p>\n<pre><code class=\"python\">\/\/ Tremor Button [v0.2.0]  import React from \"react\" import { Slot } from \"@radix-ui\/react-slot\" import { RiLoader2Fill } from \"@remixicon\/react\" import { tv, type VariantProps } from \"tailwind-variants\"   import { cx, focusRing } from \"@\/lib\/utils\"   const buttonVariants = tv({  base: [    \/\/ base    \"relative inline-flex items-center justify-center whitespace-nowrap rounded-md border px-3 py-2 text-center text-sm font-medium shadow-sm transition-all duration-100 ease-in-out\",    \/\/ disabled    \"disabled:pointer-events-none disabled:shadow-none\",    \/\/ focus    focusRing,  ],  variants: {    variant: {      primary: [        \/\/ border        \"border-transparent\",        \/\/ text color        \"text-white dark:text-white\",        \/\/ background color        \"bg-blue-500 dark:bg-blue-500\",        \/\/ hover color        \"hover:bg-blue-600 dark:hover:bg-blue-600\",        \/\/ disabled        \"disabled:bg-blue-300 disabled:text-white\",        \"disabled:dark:bg-blue-800 disabled:dark:text-blue-400\",      ],      secondary: [        \/\/ border        \"border-gray-300 dark:border-gray-800\",        \/\/ text color        \"text-gray-900 dark:text-gray-50\",        \/\/ background color        \"bg-white dark:bg-gray-950\",        \/\/hover color        \"hover:bg-gray-50 dark:hover:bg-gray-900\/60\",        \/\/ disabled        \"disabled:text-gray-400\",        \"disabled:dark:text-gray-600\",      ],      light: [        \/\/ base        \"shadow-none\",        \/\/ border        \"border-transparent\",        \/\/ text color        \"text-gray-900 dark:text-gray-50\",        \/\/ background color        \"bg-gray-200 dark:bg-gray-900\",        \/\/ hover color        \"hover:bg-gray-300\/70 dark:hover:bg-gray-800\/80\",        \/\/ disabled        \"disabled:bg-gray-100 disabled:text-gray-400\",        \"disabled:dark:bg-gray-800 disabled:dark:text-gray-600\",      ],      ghost: [        \/\/ base        \"shadow-none\",        \/\/ border        \"border-transparent\",        \/\/ text color        \"text-gray-900 dark:text-gray-50\",        \/\/ hover color        \"bg-transparent hover:bg-gray-100 dark:hover:bg-gray-800\/80\",        \/\/ disabled        \"disabled:text-gray-400\",        \"disabled:dark:text-gray-600\",      ],      destructive: [        \/\/ text color        \"text-white\",        \/\/ border        \"border-transparent\",        \/\/ background color        \"bg-red-600 dark:bg-red-700\",        \/\/ hover color        \"hover:bg-red-700 dark:hover:bg-red-600\",        \/\/ disabled        \"disabled:bg-red-300 disabled:text-white\",        \"disabled:dark:bg-red-950 disabled:dark:text-red-400\",      ],    },  },  defaultVariants: {    variant: \"primary\",  }, })   interface ButtonProps  extends React.ComponentPropsWithoutRef&lt;\"button\"&gt;,    VariantProps&lt;typeof buttonVariants&gt; {  asChild?: boolean  isLoading?: boolean  loadingText?: string }   const Button = React.forwardRef&lt;HTMLButtonElement, ButtonProps&gt;(  (    {      asChild,      isLoading = false,      loadingText,      className,      disabled,      variant,      children,      ...props    }: ButtonProps,    forwardedRef,  ) =&gt; {    const Component = asChild ? Slot : \"button\"    return (      &lt;Component        ref={forwardedRef}        className={cx(buttonVariants({ variant }), className)}        disabled={disabled || isLoading}        tremor-id=\"tremor-raw\"        {...props}      &gt;        {isLoading ? (          &lt;span className=\"pointer-events-none flex shrink-0 items-center justify-center gap-1.5\"&gt;            &lt;RiLoader2Fill              className=\"size-4 shrink-0 animate-spin\"              aria-hidden=\"true\"            \/&gt;            &lt;span className=\"sr-only\"&gt;              {loadingText ? loadingText : \"Loading\"}            &lt;\/span&gt;            {loadingText ? loadingText : children}          &lt;\/span&gt;        ) : (          children        )}      &lt;\/Component&gt;    )  }, )   Button.displayName = \"Button\"   export { Button, buttonVariants, type ButtonProps }<\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"python\">import { Button } from '@\/components\/Button';  export const ButtonHero = () =&gt; (  &lt;div className=\"flex justify-center\"&gt;    &lt;Button asChild&gt;      &lt;a href=\"#hello\"&gt;Hello, Habr!&lt;\/a&gt;    &lt;\/Button&gt;  &lt;\/div&gt; );<\/code><\/pre>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e! \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/75e\/768\/470\/75e768470d8c46bff3aa31d6965b050d.png\" width=\"222\" height=\"106\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/75e\/768\/470\/75e768470d8c46bff3aa31d6965b050d.png\"\/><\/figure>\n<h2>Planby<\/h2>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/0ea\/0c6\/5fd\/0ea0c65fda19f45ad506cd6d317168ca.jpg\" width=\"2229\" height=\"711\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0ea\/0c6\/5fd\/0ea0c65fda19f45ad506cd6d317168ca.jpg\" data-blurred=\"true\"\/><\/figure>\n<p>\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 <a href=\"https:\/\/github.com\/karolkozer\/planby\">React-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/a> \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0442\u0430\u0439\u043c\u043b\u0430\u0439\u043d\u043e\u0432, \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0439 \u0438 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c \u0413\u0430\u043d\u0442\u0430. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0440\u043e\u0434\u0435 Recharts \u0438\u043b\u0438 Nivo, Planby \u0437\u0430\u0442\u043e\u0447\u0435\u043d \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u0434 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0448\u043a\u0430\u043b\u044b \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043e\u0431\u044a\u0435\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043d\u0430 \u0445\u043e\u0440\u043e\u0448\u0430 \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0442\u044b\u0441\u044f\u0447\u0430\u043c\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0443, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0448\u043a\u0430\u043b\u044b \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. Planby \u0443\u0434\u043e\u0431\u0435\u043d \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0432 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b, \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438 \u0438 \u043b\u044e\u0431\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0433\u0434\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u044b.<\/p>\n<p><strong>\u041f\u043b\u044e\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0432 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0438 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041c\u0438\u043d\u0443\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u0430\u0439\u043c\u043b\u0430\u0439\u043d\u043e\u0432 \u0438 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e;<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u0438\u043b\u0435\u0439 \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0439 \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u0438 \u043f\u043e\u0434 \u0434\u0438\u0437\u0430\u0439\u043d \u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/karolkozer\/planby\"><strong>GitHub<\/strong><\/a>:<\/p>\n<ul>\n<li>\n<p>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0432\u0435\u0437\u0434: 1,5 \u0442\u044b\u0441.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 Issues: 6.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0435\u0440\u0441\u0438\u044f: 1.1.7.<\/p>\n<\/li>\n<li>\n<p>\u0413\u043e\u0434 \u0440\u0435\u043b\u0438\u0437\u0430: 2022.<\/p>\n<\/li>\n<li>\n<p>Merge Requests (MRs): \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e. \u0421\u0435\u0439\u0447\u0430\u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 MRs \u0438 \u043d\u0435\u0442, \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u043d\u043e\u0441\u0438\u043b\u0438\u0441\u044c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u0432\u0430 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434.<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435, \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443 \u0438\u043b\u0438 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443 \u0413\u0430\u043d\u0442\u0430 \u0432 React, Planby \u2014 \u043e\u0434\u043d\u043e \u0438\u0437 \u043b\u0443\u0447\u0448\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439.<\/p>\n<h3>\u0415\u0449\u0435 \u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u043e\u0440\u043e\u043d\u0430\u0445<\/h3>\n<p>\u0415\u0441\u0442\u044c \u0442\u0440\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Planby.<\/p>\n<p><strong>\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d<\/strong>:<\/p>\n<pre><code class=\"python\">import { useEpg, Epg, Layout } from 'planby';  const channels = React.useMemo(   () =&gt; [     {       logo: 'https:\/\/via.placeholder.com',       uuid: '10339a4b-7c48-40ab-abad-f3bcaf95d9fa',       ...     },   ],   [] );  const epg = React.useMemo(   () =&gt; [     {       channelUuid: '30f5ff1c-1346-480a-8047-a999dd908c1e',       description:         'Ut anim nisi consequat minim deserunt...',       id: 'b67ccaa3-3dd2-4121-8256-33dbddc7f0e6',       image: 'https:\/\/via.placeholder.com',       since: \"2022-02-02T23:50:00\",       till: \"2022-02-02T00:55:00\",       title: 'Title',       ...     },   ],   [] );  const {   getEpgProps,   getLayoutProps,   onScrollToNow,   onScrollLeft,   onScrollRight, } = useEpg({   epg,   channels,   startDate: '2022\/02\/02', \/\/ or 2022-02-02T00:00:00 });  return (   &lt;div&gt;     &lt;div style={{ height: '600px', width: '1200px' }}&gt;       &lt;Epg {...getEpgProps()}&gt;         &lt;Layout           {...getLayoutProps()}         \/&gt;       &lt;\/Epg&gt;     &lt;\/div&gt;   &lt;\/div&gt; );<\/code><\/pre>\n<p><strong>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0448\u0438\u0440\u0438\u043d\u044b \u0438 \u0432\u044b\u0441\u043e\u0442\u044b<\/strong>:<\/p>\n<pre><code class=\"python\">const {   getEpgProps,   getLayoutProps,   ... } = useEpg({   epg,   channels,  startDate: '2022\/02\/02', \/\/ or 2022-02-02T00:00:00   width: 1200,   height: 600 });  return (   &lt;div&gt;      &lt;Epg {...getEpgProps()}&gt;         &lt;Layout           {...getLayoutProps()}         \/&gt;       &lt;\/Epg&gt;   &lt;\/div&gt;<\/code><\/pre>\n<p><strong>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430<\/strong>:<\/p>\n<pre><code class=\"python\">const {   getEpgProps,   getLayoutProps,   ... } = useEpg({   epg,   channels,   startDate: '2022-02-02T10:00:00',   endDate: '2022-02-02T20:00:00',   width: 1200,   height: 600 });  return (   &lt;div&gt;      &lt;Epg {...getEpgProps()}&gt;         &lt;Layout           {...getLayoutProps()}         \/&gt;       &lt;\/Epg&gt;   &lt;\/div&gt;<\/code><\/pre>\n<p>\u0422\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u043a\u0440\u043e\u043b\u043b:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/3ed\/1ea\/6f0\/3ed1ea6f08f9de8b330466f85d90c38d.png\" width=\"1280\" height=\"721\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3ed\/1ea\/6f0\/3ed1ea6f08f9de8b330466f85d90c38d.png\"\/><\/figure>\n<h2>React DnD<\/h2>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/5a0\/c67\/6b8\/5a0c676b884ff7bddb0aa83a32ed6a1c.jpg\" width=\"895\" height=\"135\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5a0\/c67\/6b8\/5a0c676b884ff7bddb0aa83a32ed6a1c.jpg\" data-blurred=\"true\"\/><\/figure>\n<p><a href=\"https:\/\/react-dnd.github.io\/react-dnd\/\">React DnD<\/a> \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 Drag &amp; Drop \u0432 React \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 HTML5 API. \u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 React-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0443\u043f\u0440\u043e\u0449\u0430\u044f \u043a\u043e\u0434. \u0415\u0449\u0435 \u043e\u0434\u043d\u043e \u0434\u043e\u0441\u0442\u043e\u0438\u043d\u0441\u0442\u0432\u043e \u2014 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a <strong>react-beautiful-dnd<\/strong>, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0433\u0438\u0431\u043a\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u043e\u0432 (<strong>useDrag<\/strong> \u0438 <strong>useDrop<\/strong>) \u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u0432, \u0442\u0430\u043a \u0447\u0442\u043e \u043e\u043d\u0430 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0435\u0435. React DnD \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438, \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0441\u043f\u0438\u0441\u043a\u0430\u043c\u0438 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432 Redux.<\/p>\n<p><strong>\u041f\u043b\u044e\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u0430\u044f, \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 React;<\/p>\n<\/li>\n<li>\n<p>\u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u2014 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u044e\u0431\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0445\u043e\u0440\u043e\u0448\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041c\u0438\u043d\u0443\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0432 \u043e\u0441\u0432\u043e\u0435\u043d\u0438\u0438, \u0447\u0435\u043c <strong>react-beautiful-dnd<\/strong>;<\/p>\n<\/li>\n<li>\n<p>\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <strong>useDrag<\/strong> \u0438 <strong>useDro<\/strong>p, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e.<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/react-dnd\/react-dnd\"><strong>GitHub<\/strong><\/a>:<\/p>\n<ul>\n<li>\n<p>\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0432\u0435\u0437\u0434: 21,3 \u0442\u044b\u0441.;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 Issues: 435;<\/p>\n<\/li>\n<li>\n<p>\u0432\u0435\u0440\u0441\u0438\u044f: 16.0.0;<\/p>\n<\/li>\n<li>\n<p>\u0433\u043e\u0434 \u0440\u0435\u043b\u0438\u0437\u0430: 2014;<\/p>\n<\/li>\n<li>\n<p>Merge Requests (MRs): \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e.<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0443\u0436\u0435\u043d \u0433\u0438\u0431\u043a\u0438\u0439 \u0438 \u043c\u043e\u0449\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f Drag &amp; Drop, React DnD \u2014 \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440. \u041d\u043e \u0435\u0441\u043b\u0438 \u0437\u0430\u0434\u0430\u0447\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435, \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>react-beautiful-dnd<\/strong>.<\/p>\n<h3>\u0415\u0449\u0435 \u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u043e\u0440\u043e\u043d\u0430\u0445<\/h3>\n<p>\u0412 React DnD \u0434\u0432\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430: <a href=\"https:\/\/react-dnd.github.io\/react-dnd\/docs\/api\/dnd-provider\">DndProvider<\/a> \u0438 <a href=\"https:\/\/react-dnd.github.io\/react-dnd\/docs\/api\/drag-preview-image\">DragPreviewImage<\/a>, \u2014 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438.<\/p>\n<p>DndProvider \u2014 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 React-DnD \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0414\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0432 \u0431\u044d\u043a\u0435\u043d\u0434 \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <strong>backend<\/strong>, \u0430 \u0435\u0449\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <strong>window.<\/strong><\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"python\">import { HTML5Backend } from 'react-dnd-html5-backend' import { DndProvider } from 'react-dnd'  export default class YourApp {   render() {     return (       &lt;DndProvider backend={HTML5Backend}&gt;         \/* \u0412\u0430\u0448\u0435 Drag-and-Drop \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 *\/       &lt;\/DndProvider&gt;     )   } }<\/code><\/pre>\n<p>DragPreviewImage \u2014 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442 HTML-\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0442\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u043c\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430:<\/p>\n<pre><code class=\"python\">import { DragSource, DragPreviewImage } from 'react-dnd'  function DraggableHouse({ connectDragSource, connectDragPreview }) {   return (     &lt;&gt;       &lt;DragPreviewImage src=\"sun_dragged.png\" connect={connectDragPreview} \/&gt;       &lt;div ref={connectDragSource}&gt;\u2600\ufe0f&lt;\/div&gt;     &lt;\/&gt;   ) } export default DragSource(   \/* ... *\/   (connect, monitor) =&gt; ({     connectDragSource: connect.dragSource(),     connectDragPreview: connect.dragPreview()   }) )<\/code><\/pre>\n<h2>Advanced Cropper<\/h2>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/adb\/ac1\/d93\/adbac1d93df6e67b168a8f96326e715e.jpg\" width=\"1103\" height=\"118\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/adb\/ac1\/d93\/adbac1d93df6e67b168a8f96326e715e.jpg\" data-blurred=\"true\"\/><\/figure>\n<p>Advanced Cropper \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0442\u043e\u0447\u043d\u043e\u0433\u043e \u043a\u0430\u0434\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432 React. \u041e\u043d\u0430 \u0434\u0430\u0435\u0442 \u0433\u0438\u0431\u043a\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f, \u0437\u0443\u043c\u0430 \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439 \u043e\u0431\u0440\u0435\u0437\u043a\u0438. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f touch-\u0436\u0435\u0441\u0442\u044b, \u0447\u0442\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432.<\/p>\n<p>\u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e Advanced Cropper \u2014 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0433\u043b\u0443\u0431\u043e\u043a\u043e\u0439 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u0438, \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043e\u0431\u0440\u0435\u0437\u043a\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 canvas-\u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0443, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438.<\/p>\n<p><strong>\u041f\u043b\u044e\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0437\u0443\u043c\u0430, \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043e\u0431\u0440\u0435\u0437\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c: \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0438 UI \u043f\u043e\u0434 \u0441\u0432\u043e\u0438 \u043d\u0443\u0436\u0434\u044b;<\/p>\n<\/li>\n<li>\n<p>\u0445\u043e\u0440\u043e\u0448\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041c\u0438\u043d\u0443\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 canvas, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u0430 \u0433\u043b\u0443\u0431\u043e\u043a\u0430\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u0441\u0430\u043c\u044b\u0439 \u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442.<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/advanced-cropper\/react-advanced-cropper\"><strong>GitHub<\/strong><\/a>:<\/p>\n<ul>\n<li>\n<p>\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0432\u0435\u0437\u0434: 763;\u00a0<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 Issues: 23;<\/p>\n<\/li>\n<li>\n<p>\u0432\u0435\u0440\u0441\u0438\u044f: 0.20.1;<\/p>\n<\/li>\n<li>\n<p>\u0433\u043e\u0434 \u0440\u0435\u043b\u0438\u0437\u0430: 2021;<\/p>\n<\/li>\n<li>\n<p>Merge Requests (MRs): \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e.<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u0430\u044f \u043e\u0431\u0440\u0435\u0437\u043a\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0441 \u0442\u043e\u0447\u043d\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438, Advanced Cropper \u2014 \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440.\u00a0<\/p>\n<h3>\u0415\u0449\u0435 \u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u043e\u0440\u043e\u043d\u0430\u0445<\/h3>\n<p>\u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"python\">import React, { useState } from 'react'; import { CropperRef, Cropper } from 'react-advanced-cropper'; import 'react-advanced-cropper\/dist\/style.css'  export const GettingStartedExample = () =&gt; {     const [image, setImage] = useState( 'https:\/\/cdn.prod.website-files.com\/65cb50148a423f63add18bc6\/65ce1bf224944099ef1159b3_habr.png',     );      const onChange = (cropper: CropperRef) =&gt; {         console.log(cropper.getCoordinates(), cropper.getCanvas());     };      return (         &lt;Cropper             src={image}             onChange={onChange}             className={'cropper'}         \/&gt;     ) };<\/code><\/pre>\n<p>\u041d\u0430 \u043a\u043e\u043b\u0435\u0441\u0438\u043a\u043e \u043c\u044b\u0448\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0437\u0443\u043c:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/15a\/1e6\/c24\/15a1e6c248619b9d736bd5401bc3823c.jpg\" width=\"266\" height=\"323\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/15a\/1e6\/c24\/15a1e6c248619b9d736bd5401bc3823c.jpg\" data-blurred=\"true\"\/><\/figure>\n<h2>React Resizable Panels<\/h2>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/edf\/93f\/679\/edf93f67990b8bd96b16e56cc35f04b7.png\" width=\"656\" height=\"320\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/edf\/93f\/679\/edf93f67990b8bd96b16e56cc35f04b7.png\"\/><\/figure>\n<p>React Resizable Panels \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0445 \u043f\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0443 \u043f\u0430\u043d\u0435\u043b\u0435\u0439 \u0432 React-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445. \u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0442\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043c\u0435\u0436\u0434\u0443 \u043f\u0430\u043d\u0435\u043b\u044f\u043c\u0438, \u043c\u0435\u043d\u044f\u0442\u044c \u0438\u0445 \u0448\u0438\u0440\u0438\u043d\u0443 \u0438\u043b\u0438 \u0432\u044b\u0441\u043e\u0442\u0443. \u041e\u0442\u043c\u0435\u0447\u0443 \u0435\u0449\u0435 \u0433\u043b\u0430\u0434\u043a\u0438\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438 \u0438 \u043e\u0442\u0437\u044b\u0432\u0447\u0438\u0432\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.<\/p>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0440\u0443\u0447\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 <strong>div <\/strong>\u0438 <strong>onMouseMove<\/strong>, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0440\u0435\u0448\u0430\u0435\u0442 \u0432\u0441\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u043e\u0439, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0438 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u0441 \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u044b\u043c \u0434\u0438\u0437\u0430\u0439\u043d\u043e\u043c. \u041c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0433\u0438\u0431\u043a\u0438\u0435 \u043b\u0435\u0439\u0430\u0443\u0442\u044b, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0431\u043e\u043a\u043e\u0432\u044b\u0435 \u043f\u0430\u043d\u0435\u043b\u0438, \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u044b \u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u0431\u043b\u0430\u0441\u0442\u044f\u043c\u0438 \u0438 \u043c\u043d\u043e\u0433\u043e\u0441\u0435\u043a\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b.<\/p>\n<p><strong>\u041f\u043b\u044e\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0438 \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 API;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f\u043c\u0438 \u0438 \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u044b\u043c \u0434\u0438\u0437\u0430\u0439\u043d\u043e\u043c.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041c\u0438\u043d\u0443\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0430\u043d\u0435\u043b\u044f\u043c\u0438, \u0434\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043b\u0435\u0439\u0430\u0443\u0442\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f CSS Grid \u0438\u043b\u0438 Flexbox.<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/bvaughn\/react-resizable-panels\"><strong>GitHub<\/strong><\/a>:<\/p>\n<ul>\n<li>\n<p>\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0432\u0435\u0437\u0434: 4,3 \u0442\u044b\u0441.;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 Issues: 17;<\/p>\n<\/li>\n<li>\n<p>\u0432\u0435\u0440\u0441\u0438\u044f: 2.1.7;<\/p>\n<\/li>\n<li>\n<p>\u0433\u043e\u0434 \u0440\u0435\u043b\u0438\u0437\u0430: 2022;<\/p>\n<\/li>\n<li>\n<p>Merge Requests (MRs): \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e.<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432 \u043f\u0430\u043d\u0435\u043b\u0435\u0439 \u0431\u0435\u0437 \u0431\u043e\u043b\u0438, React Resizable Panels \u2014 \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u041e\u043d\u043e \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u043a\u043e\u0434\u0430, \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u0432 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441 \u0433\u0438\u0431\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u043e\u0439.<\/p>\n<h3>\u0415\u0449\u0435 \u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u043e\u0440\u043e\u043d\u0430\u0445<\/h3>\n<p>\u0412 React Resizable Panels \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c <a href=\"https:\/\/react-resizable-panels.vercel.app\/examples\/horizontal\">\u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439<\/a> \u0438 <a href=\"https:\/\/react-resizable-panels.vercel.app\/examples\/vertical\">\u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439<\/a> \u043c\u0430\u043a\u0435\u0442\u044b. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043e \u043f\u0435\u0440\u0432\u043e\u043c:<\/p>\n<pre><code class=\"python\">&lt;PanelGroup direction=\"horizontal\"&gt;  &lt;Panel defaultSize={30} minSize={20}&gt;    left  &lt;\/Panel&gt;  &lt;PanelResizeHandle \/&gt;  &lt;Panel minSize={30}&gt;    middle  &lt;\/Panel&gt;  &lt;PanelResizeHandle \/&gt;  &lt;Panel defaultSize={30} minSize={20}&gt;    right  &lt;\/Panel&gt; &lt;\/PanelGroup&gt;<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440, \u043d\u0443\u0436\u043d\u043e \u043a\u043b\u0438\u043a\u043d\u0443\u0442\u044c \u043d\u0430 \u043f\u0443\u0441\u0442\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e \u043c\u0435\u0436\u0434\u0443 \u043f\u0430\u043d\u0435\u043b\u044f\u043c\u0438 \u0438 \u0437\u0430\u0436\u0430\u0442\u044c \u043b\u0435\u0432\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443 \u043c\u044b\u0448\u0438. \u041f\u043e\u0442\u043e\u043c \u0434\u0432\u0438\u0433\u0430\u0442\u044c \u043a\u0443\u0440\u0441\u043e\u0440 \u0432\u043b\u0435\u0432\u043e \u0438\u043b\u0438 \u0432\u043f\u0440\u0430\u0432\u043e \u2014 \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0430\u043d\u0435\u043b\u0435\u0439:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7b5\/5c3\/80b\/7b55c380b189b8c80a25c7411620bd92.png\" width=\"1355\" height=\"346\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7b5\/5c3\/80b\/7b55c380b189b8c80a25c7411620bd92.png\"\/><\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439:<\/p>\n<pre><code class=\"python\">&lt;PanelGroup direction=\"vertical\"&gt;  &lt;Panel maxSize={75}&gt;    top  &lt;\/Panel&gt;  &lt;PanelResizeHandle \/&gt;  &lt;Panel maxSize={75}&gt;    bottom  &lt;\/Panel&gt; &lt;\/PanelGroup&gt;<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0443\u0442 \u043f\u043e\u0445\u043e\u0436\u0438\u0439:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f40\/ba0\/10e\/f40ba010e0087c970451df941a036514.png\" width=\"1270\" height=\"309\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f40\/ba0\/10e\/f40ba010e0087c970451df941a036514.png\"\/><\/figure>\n<h2>ShadCN UI<\/h2>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/c1b\/7ea\/078\/c1b7ea0786d07b5eb084783d49cebc3f.jpg\" width=\"1250\" height=\"268\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c1b\/7ea\/078\/c1b7ea0786d07b5eb084783d49cebc3f.jpg\" data-blurred=\"true\"\/><\/figure>\n<p>ShadCN UI \u2014 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f UI-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f React, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u0430\u044f \u043f\u043e\u0432\u0435\u0440\u0445 Radix UI \u0438 \u0441\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Tailwind CSS. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, MUI \u0438\u043b\u0438 Ant Design), ShadCN \u043d\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 npm-\u043f\u0430\u043a\u0435\u0442, \u0430 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432 \u0432\u0438\u0434\u0435 \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0438\u0434\u0435\u044f ShadCN UI \u2014 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c. \u0412\u043c\u0435\u0441\u0442\u043e \u0436\u0435\u0441\u0442\u043a\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0438\u043b\u0435\u0439 \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u2014 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0438\u0445 \u043b\u0435\u0433\u043a\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u0434\u0438\u0437\u0430\u0439\u043d \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u041e\u043d\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u0438\u0441\u0442\u0438\u0447\u043d\u043e \u0438 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0435 Tailwind CSS. \u0412 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u0435\u0441\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0438, \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430, \u0434\u0438\u0430\u043b\u043e\u0433\u0438, \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0434\u0440\u043e\u043f\u0434\u0430\u0443\u043d\u044b \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b UI.<\/p>\n<p><strong>\u041f\u043b\u044e\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u043a\u043e\u0434\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u0441\u0435\u0431\u044f;<\/p>\n<\/li>\n<li>\n<p>\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 Radix UI, \u0447\u0442\u043e \u0434\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c (a11y) \u0438 \u0445\u043e\u0440\u043e\u0448\u0443\u044e \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u0441 Tailwind CSS;<\/p>\n<\/li>\n<li>\n<p>\u043c\u0438\u043d\u0438\u043c\u0430\u043b\u0438\u0441\u0442\u0438\u0447\u043d\u044b\u0439 \u0434\u0438\u0437\u0430\u0439\u043d, \u043b\u0435\u0433\u043a\u043e \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 UI.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041c\u0438\u043d\u0443\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u043d\u0443\u0436\u043d\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u0442\u0430\u043a\u0430\u044f \u0431\u043e\u0433\u0430\u0442\u0430\u044f \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0430, \u043a\u0430\u043a \u0443 Ant Design \u0438\u043b\u0438 MUI;<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u043f\u043e\u0434\u043e\u0439\u0442\u0438, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u0435\u043d \u043f\u043e\u043b\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u00ab\u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438\u00bb.<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/shadcn-ui\/ui\"><strong>GitHub<\/strong><\/a>:<\/p>\n<ul>\n<li>\n<p>\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0432\u0435\u0437\u0434: 83,6 \u0442\u044b\u0441.;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 Issues: 840;<\/p>\n<\/li>\n<li>\n<p>\u0432\u0435\u0440\u0441\u0438\u044f: 2.3.0;<\/p>\n<\/li>\n<li>\n<p>\u0433\u043e\u0434 \u0440\u0435\u043b\u0438\u0437\u0430: 2023;<\/p>\n<\/li>\n<li>\n<p>Merge Requests (MRs): \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e.\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>ShadCN UI \u2014 \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u0432\u044b\u0431\u043e\u0440 \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c Tailwind CSS, \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e Radix UI \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u043a\u043e\u0434\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432. \u042d\u0442\u043e \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0434\u043b\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0434\u0438\u0437\u0430\u0439\u043d-\u0441\u0438\u0441\u0442\u0435\u043c \u0438 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 React-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<h3>\u0415\u0449\u0435 \u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u043e\u0440\u043e\u043d\u0430\u0445<\/h3>\n<p>\u0412 ShadCN UI \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432: Accordion (\u043d\u0435 \u043c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0430\u043a\u043a\u043e\u0440\u0434\u0435\u043e\u043d, \u0430 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432, \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u0432\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442), Alert, Card, Chart, Checkbox, Data Table, Dialog, Drawer, Menubar \u0438 \u0434\u0440\u0443\u0433\u0438\u0435.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c <a href=\"https:\/\/ui.shadcn.com\/docs\/components\/menubar\">Menubar<\/a>, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u044b:<\/p>\n<pre><code class=\"python\">import {   Menubar,   MenubarContent,   MenubarItem,   MenubarMenu,   MenubarSeparator,   MenubarShortcut,   MenubarTrigger, } from \"@\/components\/ui\/menubar\"<\/code><\/pre>\n<p>\u0418 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443:<\/p>\n<pre><code class=\"python\">&lt;Menubar&gt;     &lt;MenubarMenu&gt;         &lt;MenubarTrigger&gt;File&lt;\/MenubarTrigger&gt;         &lt;MenubarContent&gt;             &lt;MenubarItem&gt;                 New Tab &lt;MenubarShortcut&gt;\u2318T&lt;\/MenubarShortcut&gt;             &lt;\/MenubarItem&gt;             &lt;MenubarItem&gt;New Window&lt;\/MenubarItem&gt;           &lt;MenubarSeparator \/&gt;            &lt;MenubarItem&gt;Share&lt;\/MenubarItem&gt;             &lt;MenubarSeparator \/&gt;             &lt;MenubarItem&gt;Print&lt;\/MenubarItem&gt;         &lt;\/MenubarContent&gt;     &lt;\/MenubarMenu&gt; &lt;\/Menubar&gt;<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Menubar:  <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9fb\/5cc\/8ff\/9fb5cc8ffdffad88bbd6ab52a8324034.png\" width=\"577\" height=\"310\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9fb\/5cc\/8ff\/9fb5cc8ffdffad88bbd6ab52a8324034.png\"\/><\/figure>\n<p>\u041d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0432\u0441\u0435. \u0421\u0435\u0439\u0447\u0430\u0441 \u0434\u0443\u043c\u0430\u044e \u0435\u0449\u0435 \u043d\u0430\u0434 \u043f\u0430\u0440\u043e\u0439 \u043f\u043e\u0434\u0431\u043e\u0440\u043e\u043a \u0441 \u0445\u043e\u0440\u043e\u0448\u043e \u0437\u0430\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u0432\u0448\u0438\u043c\u0438 \u0441\u0435\u0431\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438. \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445, \u0447\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435\u0441\u044c \u0432\u044b, \u2014 \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u043e\u0441\u0442 \u0435\u0449\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u0435\u0435!<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/892964\/\"> https:\/\/habr.com\/ru\/articles\/892964\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440\u0447\u0430\u043d\u0435! \u042d\u0442\u043e \u041b\u0435\u0448\u0430 \u0416\u0438\u0440\u044f\u043a\u043e\u0432, \u0442\u0435\u0445\u043b\u0438\u0434 backend-\u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u0438\u0442\u0440\u0438\u043d\u044b KION. \u0412 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437 \u044f \u043f\u0438\u0441\u0430\u043b <a href=\"https:\/\/habr.com\/ru\/companies\/ru_mts\/articles\/884376\/\">\u043e \u0441\u0435\u043a\u0440\u0435\u0442\u0430\u0445 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 Python<\/a>, \u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0442 \u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043d\u0430 React. \u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0441\u0442\u043e\u0438\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u0432\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0432 2025 \u0433\u043e\u0434\u0443, \u043f\u0440\u0438\u0432\u0435\u0434\u0443 \u043f\u043b\u044e\u0441\u044b \u0438 \u043c\u0438\u043d\u0443\u0441\u044b \u043a\u0430\u0436\u0434\u043e\u0439, \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 GitHub \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u0430\u0447\u043d\u0435\u043c!<\/p>\n<h2>Tremor<\/h2>\n<figure class=\"full-width\"><\/figure>\n<p><a href=\"https:\/\/tremor.so\/\">Tremor<\/a> \u2014 UI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u0432 \u0438 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0432 React. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u0437\u0430\u0442\u043e\u0447\u0435\u043d\u043d\u044b\u0445 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, Tremor \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 UI-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b: \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0438, \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043a\u043d\u043e\u043f\u043a\u0438, \u0433\u0440\u0430\u0444\u0438\u043a\u0438, \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043d\u0430 Tailwind CSS (\u043e\u0431 \u044d\u0442\u043e\u043c \u0432 \u0431\u043b\u043e\u0433\u0435 <a href=\"https:\/\/habr.com\/ru\/companies\/ru_mts\/articles\/860534\/\">\u043f\u0438\u0441\u0430\u043b<\/a> \u043a\u043e\u043b\u043b\u0435\u0433\u0430), \u0442\u0430\u043a \u0447\u0442\u043e \u043e\u043d\u0430 \u0443\u0434\u043e\u0431\u043d\u0430 \u0434\u043b\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0438\u0434\u0435\u044f Tremor \u2014 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u043e\u0432, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0445\u043e\u0440\u043e\u0448\u043e \u0441\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0438 \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u0437\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u043e\u0447\u043a\u0443 \u0441 \u043a\u043b\u044e\u0447\u0435\u0432\u043e\u0439 \u043c\u0435\u0442\u0440\u0438\u043a\u043e\u0439 \u0438\u043b\u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443 \u0438\u0437 Recharts, Nivo \u0438\u043b\u0438 ECharts. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043c\u043d\u0430\u044f \u0438 \u0441\u0432\u0435\u0442\u043b\u0430\u044f \u0442\u0435\u043c\u044b, \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0430 \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u044f \u043a \u0440\u0430\u0437\u043d\u044b\u043c \u044d\u043a\u0440\u0430\u043d\u0430\u043c.<\/p>\n<p><strong>\u041f\u043b\u044e\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0433\u043e\u0442\u043e\u0432\u044b\u0435 UI-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043b\u0435\u0433\u043a\u0430\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Recharts, Nivo \u0438 ECharts;<\/p>\n<\/li>\n<li>\n<p>\u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f Tailwind CSS.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041c\u0438\u043d\u0443\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u0430\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0432 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0438 \u0441 \u0447\u0438\u0441\u0442\u044b\u043c\u0438 UI-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430\u043c\u0438;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0438 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/tremorlabs\/tremor\"><strong>GitHub<\/strong><\/a>:<\/p>\n<ul>\n<li>\n<p>\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0432\u0435\u0437\u0434: 2,1 \u0442\u044b\u0441.;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 Issues: 11;<\/p>\n<\/li>\n<li>\n<p>\u0433\u043e\u0434 \u0440\u0435\u043b\u0438\u0437\u0430: 2024;<\/p>\n<\/li>\n<li>\n<p>Merge Requests (MRs): \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0434\u0430\u0448\u0431\u043e\u0440\u0434 \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0443\u0441\u0438\u043b\u0438\u044f\u043c\u0438, \u043d\u043e \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u0435 UI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<\/p>\n<h3>\u0415\u0449\u0435 \u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u043e\u0440\u043e\u043d\u0430\u0445<\/h3>\n<p>Tremor \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432: \u0433\u0440\u0430\u0444\u0438\u043a\u0438 (Area Chart, Bar Chart, Donut Chart, Progress Bar), \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 (Calendar, Checkbox, Date Picker, Radio Card Group) \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 UI-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b (Badge, Button, Dialog, Table).<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443 (<a href=\"https:\/\/tremor.so\/docs\/ui\/button\">Button<\/a>). \u0412 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Tremor \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d: Ctrl + C, Ctrl + V \u2014 \u0438 \u0432\u043f\u0435\u0440\u0435\u0434!<\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"python\">npm install @radix-ui\/react-slot tailwind-variants @remixicon\/react<\/code><\/pre>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u0434 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b. \u0412\u0430\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u044b:<\/p>\n<pre><code class=\"python\">\/\/ Tremor Button [v0.2.0]  import React from \"react\" import { Slot } from \"@radix-ui\/react-slot\" import { RiLoader2Fill } from \"@remixicon\/react\" import { tv, type VariantProps } from \"tailwind-variants\"   import { cx, focusRing } from \"@\/lib\/utils\"   const buttonVariants = tv({  base: [    \/\/ base    \"relative inline-flex items-center justify-center whitespace-nowrap rounded-md border px-3 py-2 text-center text-sm font-medium shadow-sm transition-all duration-100 ease-in-out\",    \/\/ disabled    \"disabled:pointer-events-none disabled:shadow-none\",    \/\/ focus    focusRing,  ],  variants: {    variant: {      primary: [        \/\/ border        \"border-transparent\",        \/\/ text color        \"text-white dark:text-white\",        \/\/ background color        \"bg-blue-500 dark:bg-blue-500\",        \/\/ hover color        \"hover:bg-blue-600 dark:hover:bg-blue-600\",        \/\/ disabled        \"disabled:bg-blue-300 disabled:text-white\",        \"disabled:dark:bg-blue-800 disabled:dark:text-blue-400\",      ],      secondary: [        \/\/ border        \"border-gray-300 dark:border-gray-800\",        \/\/ text color        \"text-gray-900 dark:text-gray-50\",        \/\/ background color        \"bg-white dark:bg-gray-950\",        \/\/hover color        \"hover:bg-gray-50 dark:hover:bg-gray-900\/60\",        \/\/ disabled        \"disabled:text-gray-400\",        \"disabled:dark:text-gray-600\",      ],      light: [        \/\/ base        \"shadow-none\",        \/\/ border        \"border-transparent\",        \/\/ text color        \"text-gray-900 dark:text-gray-50\",        \/\/ background color        \"bg-gray-200 dark:bg-gray-900\",        \/\/ hover color        \"hover:bg-gray-300\/70 dark:hover:bg-gray-800\/80\",        \/\/ disabled        \"disabled:bg-gray-100 disabled:text-gray-400\",        \"disabled:dark:bg-gray-800 disabled:dark:text-gray-600\",      ],      ghost: [        \/\/ base        \"shadow-none\",        \/\/ border        \"border-transparent\",        \/\/ text color        \"text-gray-900 dark:text-gray-50\",        \/\/ hover color        \"bg-transparent hover:bg-gray-100 dark:hover:bg-gray-800\/80\",        \/\/ disabled        \"disabled:text-gray-400\",        \"disabled:dark:text-gray-600\",      ],      destructive: [        \/\/ text color        \"text-white\",        \/\/ border        \"border-transparent\",        \/\/ background color        \"bg-red-600 dark:bg-red-700\",        \/\/ hover color        \"hover:bg-red-700 dark:hover:bg-red-600\",        \/\/ disabled        \"disabled:bg-red-300 disabled:text-white\",        \"disabled:dark:bg-red-950 disabled:dark:text-red-400\",      ],    },  },  defaultVariants: {    variant: \"primary\",  }, })   interface ButtonProps  extends React.ComponentPropsWithoutRef&lt;\"button\"&gt;,    VariantProps&lt;typeof buttonVariants&gt; {  asChild?: boolean  isLoading?: boolean  loadingText?: string }   const Button = React.forwardRef&lt;HTMLButtonElement, ButtonProps&gt;(  (    {      asChild,      isLoading = false,      loadingText,      className,      disabled,      variant,      children,      ...props    }: ButtonProps,    forwardedRef,  ) =&gt; {    const Component = asChild ? Slot : \"button\"    return (      &lt;Component        ref={forwardedRef}        className={cx(buttonVariants({ variant }), className)}        disabled={disabled || isLoading}        tremor-id=\"tremor-raw\"        {...props}      &gt;        {isLoading ? (          &lt;span className=\"pointer-events-none flex shrink-0 items-center justify-center gap-1.5\"&gt;            &lt;RiLoader2Fill              className=\"size-4 shrink-0 animate-spin\"              aria-hidden=\"true\"            \/&gt;            &lt;span className=\"sr-only\"&gt;              {loadingText ? loadingText : \"Loading\"}            &lt;\/span&gt;            {loadingText ? loadingText : children}          &lt;\/span&gt;        ) : (          children        )}      &lt;\/Component&gt;    )  }, )   Button.displayName = \"Button\"   export { Button, buttonVariants, type ButtonProps }<\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0442\u0430\u043a\u043e\u0439 \u0431\u043b\u043e\u043a \u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"python\">import { Button } from '@\/components\/Button';  export const ButtonHero = () =&gt; (  &lt;div className=\"flex justify-center\"&gt;    &lt;Button asChild&gt;      &lt;a href=\"#hello\"&gt;Hello, Habr!&lt;\/a&gt;    &lt;\/Button&gt;  &lt;\/div&gt; );<\/code><\/pre>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e! \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043d\u043e\u043f\u043a\u0443:<\/p>\n<figure class=\"\"><\/figure>\n<h2>Planby<\/h2>\n<figure class=\"full-width\"><\/figure>\n<p>\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 <a href=\"https:\/\/github.com\/karolkozer\/planby\">React-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/a> \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0442\u0430\u0439\u043c\u043b\u0430\u0439\u043d\u043e\u0432, \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0439 \u0438 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c \u0413\u0430\u043d\u0442\u0430. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0440\u043e\u0434\u0435 Recharts \u0438\u043b\u0438 Nivo, Planby \u0437\u0430\u0442\u043e\u0447\u0435\u043d \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u0434 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0448\u043a\u0430\u043b\u044b \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043e\u0431\u044a\u0435\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043d\u0430 \u0445\u043e\u0440\u043e\u0448\u0430 \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0442\u044b\u0441\u044f\u0447\u0430\u043c\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0443, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0448\u043a\u0430\u043b\u044b \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. Planby \u0443\u0434\u043e\u0431\u0435\u043d \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0432 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u044b, \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438 \u0438 \u043b\u044e\u0431\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0433\u0434\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u044b.<\/p>\n<p><strong>\u041f\u043b\u044e\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0432 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0438 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041c\u0438\u043d\u0443\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0442\u0430\u0439\u043c\u043b\u0430\u0439\u043d\u043e\u0432 \u0438 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e;<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u0438\u043b\u0435\u0439 \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0439 \u0430\u0434\u0430\u043f\u0442\u0430\u0446\u0438\u0438 \u043f\u043e\u0434 \u0434\u0438\u0437\u0430\u0439\u043d \u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/karolkozer\/planby\"><strong>GitHub<\/strong><\/a>:<\/p>\n<ul>\n<li>\n<p>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0432\u0435\u0437\u0434: 1,5 \u0442\u044b\u0441.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 Issues: 6.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0435\u0440\u0441\u0438\u044f: 1.1.7.<\/p>\n<\/li>\n<li>\n<p>\u0413\u043e\u0434 \u0440\u0435\u043b\u0438\u0437\u0430: 2022.<\/p>\n<\/li>\n<li>\n<p>Merge Requests (MRs): \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e. \u0421\u0435\u0439\u0447\u0430\u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0445 MRs \u0438 \u043d\u0435\u0442, \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u043d\u043e\u0441\u0438\u043b\u0438\u0441\u044c \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u0432\u0430 \u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434.<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435, \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443 \u0438\u043b\u0438 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443 \u0413\u0430\u043d\u0442\u0430 \u0432 React, Planby \u2014 \u043e\u0434\u043d\u043e \u0438\u0437 \u043b\u0443\u0447\u0448\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439.<\/p>\n<h3>\u0415\u0449\u0435 \u043e \u0441\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u043e\u0440\u043e\u043d\u0430\u0445<\/h3>\n<p>\u0415\u0441\u0442\u044c \u0442\u0440\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Planby.<\/p>\n<p><strong>\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0448\u0430\u0431\u043b\u043e\u043d<\/strong>:<\/p>\n<pre><code class=\"python\">import { useEpg, Epg, Layout } from 'planby';  const channels = React.useMemo(   () =&gt; [     {       logo: 'https:\/\/via.placeholder.com',       uuid: '10339a4b-7c48-40ab-abad-f3bcaf95d9fa',       ...     },   ],   [] );  const epg = React.useMemo(   () =&gt; [     {       channelUuid: '30f5ff1c-1346-480a-8047-a999dd908c1e',       description:         'Ut anim nisi consequat minim deserunt...',       id: 'b67ccaa3-3dd2-4121-8256-33dbddc7f0e6',       image: 'https:\/\/via.placeholder.com',       since: \"2022-02-02T23:50:00\",       till: \"2022-02-02T00:55:00\",       title: 'Title',       ...     },   ],   [] );  const {   getEpgProps,   getLayoutProps,   onScrollToNow,   onScrollLeft,   onScrollRight, } = useEpg({   epg,   channels,   startDate: '2022\/02\/02', \/\/ or 2022-02-02T00:00:00 });  return (   &lt;div&gt;     &lt;div style={{ height: '600px', width: '1200px' }}&gt;       &lt;Epg {...getEpgProps()}&gt;         &lt;Layout           {...getLayoutProps()}         \/&gt;       &lt;\/Epg&gt;     &lt;\/div&gt;   &lt;\/div&gt; );<\/code><\/pre>\n<p><strong>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0448\u0438\u0440\u0438\u043d\u044b \u0438 \u0432\u044b\u0441\u043e\u0442\u044b<\/strong>:<\/p>\n<pre><code class=\"python\">const {   getEpgProps,   getLayoutProps,   ... } = useEpg({   epg,   channels,  startDate: '2022\/02\/02', \/\/ or 2022-02-02T00:00:00   width: 1200,   height: 600 });  return (   &lt;div&gt;      &lt;Epg {...getEpgProps()}&gt;         &lt;Layout           {...getLayoutProps()}         \/&gt;       &lt;\/Epg&gt;   &lt;\/div&gt;<\/code><\/pre>\n<p><strong>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430<\/strong>:<\/p>\n<pre><code class=\"python\">const {   getEpgProps,   getLayoutProps,   ... } = useEpg({   epg,   channels,   startDate: '2022-02-02T10:00:00',   endDate: '2022-02-02T20:00:00',   width: 1200,   height: 600 });  return (   &lt;div&gt;      &lt;Epg {...getEpgProps()}&gt;         &lt;Layout           {...getLayoutProps()}         \/&gt;       &lt;\/Epg&gt;   &lt;\/div&gt;<\/code><\/pre>\n<p>\u0422\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u043a\u0440\u043e\u043b\u043b:<\/p>\n<figure class=\"full-width\"><\/figure>\n<h2>React DnD<\/h2>\n<figure class=\"full-width\"><\/figure>\n<p><a href=\"https:\/\/react-dnd.github.io\/react-dnd\/\">React DnD<\/a> \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 Drag &amp; Drop \u0432 React \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 HTML5 API. \u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 React-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0443\u043f\u0440\u043e\u0449\u0430\u044f \u043a\u043e\u0434. \u0415\u0449\u0435 \u043e\u0434\u043d\u043e \u0434\u043e\u0441\u0442\u043e\u0438\u043d\u0441\u0442\u0432\u043e \u2014 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a <strong>react-beautiful-dnd<\/strong>, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u0433\u0438\u0431\u043a\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u043e\u0432 (<strong>useDrag<\/strong> \u0438 <strong>useDrop<\/strong>) \u0438 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u0432, \u0442\u0430\u043a \u0447\u0442\u043e \u043e\u043d\u0430 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0435\u0435. React DnD \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438, \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0441\u043f\u0438\u0441\u043a\u0430\u043c\u0438 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432 Redux.<\/p>\n<p><strong>\u041f\u043b\u044e\u0441\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u0430\u044f, \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 React;<\/p>\n<\/li>\n<li>\n<p>\u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u2014 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043b\u044e\u0431\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0445\u043e\u0440\u043e\u0448\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041c<\/strong><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-452540","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/452540","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=452540"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/452540\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=452540"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=452540"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=452540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}