{"id":461593,"date":"2025-05-30T21:00:19","date_gmt":"2025-05-30T21:00:19","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=461593"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=461593","title":{"rendered":"<span>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 Angular: \u0432\u0441\u0451 \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u0441\u0442\u0440\u0430\u0448\u043d\u043e<\/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<p>\u0412\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441: \u043a\u0430\u043a \u0432\u0441\u0451 \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u043e, \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0438 \u0435\u0434\u0438\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e? \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u0441\u0451 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u043c \u2013 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 building block, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0430 \u0434\u0430\u043b\u044c\u0448\u0435 \u0447\u0435\u0440\u0435\u0434\u0443\u0439 \u0438\u043c\u0438 \u0438 \u0436\u043e\u043d\u0433\u043b\u0438\u0440\u0443\u0439, \u043a\u0430\u043a \u0434\u0443\u0448\u0435 \u0443\u0433\u043e\u0434\u043d\u043e. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043c\u043e\u0436\u043d\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0433\u043e\u0442\u043e\u0432\u044b\u0435 UI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0436\u0435 \u0432\u043b\u043e\u0436\u0435\u043d\u044b \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e-\u0447\u0430\u0441\u043e\u0432. \u041d\u043e, \u043f\u043e \u043c\u0435\u0440\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0451 \u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, \u043f\u043e\u0440\u043e\u0439 \u0432\u0441\u0442\u0430\u044e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043e\u0431\u0443\u0436\u0434\u0430\u044e\u0442 \u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0441\u0432\u043e\u0435\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e UI Kit.<\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u043c, \u043c\u0443\u0442\u043e\u0440\u043d\u044b\u043c, \u0435\u0449\u0451 \u0438 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u043c \u0442\u0435\u0445\u0441\u0442\u0435\u043a\u0435. \u0423 Angular, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u0442\u044c \u0440\u0435\u043f\u0443\u0442\u0430\u0446\u0438\u044f \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430: \u043d\u0435 \u0441\u0430\u043c\u0430\u044f \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f, \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u0448\u0438\u0440\u043e\u043a\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e \u0438 \u043c\u0435\u043d\u044c\u0448\u0430\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u044c \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 React. \u041d\u0430 \u0434\u0435\u043b\u0435 \u0432\u0441\u0451 \u043d\u0435 \u0442\u0430\u043a \u0441\u0442\u0440\u0430\u0448\u043d\u043e. Angular \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0438 \u0443\u043b\u0443\u0447\u0448\u0430\u0435\u0442\u0441\u044f, \u043f\u0440\u0438\u0442\u043e\u043c, \u043a\u0430\u043a \u0438 \u0440\u0430\u043d\u044c\u0448\u0435, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 web-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>\u042f \u0441\u0447\u0438\u0442\u0430\u044e, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 Angular \u2013 \u044d\u0442\u043e \u043d\u0435 \u043f\u043e\u0434\u0432\u0438\u0433, \u0441\u043e\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0439 \u00ab\u0432\u043e\u043f\u0440\u0435\u043a\u0438\u00bb, \u043d\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u0440\u0430\u0437\u0443\u043c\u043d\u044b\u0439 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440, \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u043e\u0439\u0442\u0438 \u043a \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e.<\/p>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u2013 \u0441\u043a\u043e\u0440\u0435\u0435, \u043e\u0431\u0437\u043e\u0440 \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043e\u0442 \u00ab\u0437\u0430\u0447\u0435\u043c\u00bb \u0434\u043e \u00ab\u043a\u0430\u043a\u00bb, \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u043c\u0438.<\/p>\n<h3>\u0410 \u043a\u0430\u043a \u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u043e\u0435?<\/h3>\n<p>\u041c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0441\u0432\u043e\u0435\u0433\u043e UI Kit, \u043a\u043e\u0433\u0434\u0430 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0437\u0440\u0435\u043b\u044b\u0445 \u0438 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a. \u0410\u0432\u0442\u043e\u0440 \u044f\u0432\u043d\u043e \u043d\u0435 \u0441\u0442\u0440\u0430\u0434\u0430\u0435\u0442 \u0441\u0438\u043d\u0434\u0440\u043e\u043c\u043e\u043c NIH. \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u0435\u0441\u0442\u044c \u0438\u0437 \u0447\u0435\u0433\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c: <a href=\"https:\/\/taiga-ui.dev\/\" rel=\"noopener noreferrer nofollow\">Taiga UI<\/a>, <a href=\"https:\/\/primeng.org\/\" rel=\"noopener noreferrer nofollow\">PrimeNG<\/a>, <a href=\"https:\/\/material.angular.dev\/\" rel=\"noopener noreferrer nofollow\">Angular Material<\/a> \u043e\u0442 \u0442\u043e\u0433\u043e \u0436\u0435 Google, \u043d\u0430\u043a\u043e\u043d\u0435\u0446.<\/p>\n<p>\u0422\u0430\u043a \u043f\u043e\u0447\u0435\u043c\u0443 \u0436\u0435 \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 UI Kit?<\/p>\n<ol>\n<li>\n<p>\u0412 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u0433\u043e \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u0425\u043e\u0442\u0435\u043b\u0438 \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f, \u043d\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043b\u0438\u0431\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c Issue\/CR\/PR \u0430\u0432\u0442\u043e\u0440\u0430\u043c \u0438 \u0436\u0434\u0430\u0442\u044c, \u043d\u0430\u0434\u0435\u044f\u0441\u044c \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u043b\u0438\u0431\u043e \u0436\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0430\u043c\u043e\u043c\u0443<\/p>\n<\/li>\n<li>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043c\u043e\u0436\u0435\u0442 \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u043e\u0432\u0441\u0435 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0442\u044c \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u00ab\u043a\u043e\u0441\u0442\u044c\u044e \u0432 \u0433\u043e\u0440\u043b\u0435\u00bb, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0442\u0430\u043d\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 \u043d\u043e\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 Angular<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u044e\u0442 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b \u0441 \u0432\u0430\u0448\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0438\u043b\u0438 \u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0432\u0430\u0441 \u043f\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u0438\u043d\u044b\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0432\u0430\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u2013 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c (A11Y) \u0438\u043b\u0438 \u0442\u0451\u043c\u043d\u0443\u044e \u0442\u0435\u043c\u0443 (Dark Mode)<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0445 (\u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0430\u043b\u044c\u0446\u0435\u043c \u043d\u0430 PrimeNG) \u0442\u0435\u043c\u044b \u0438 \u0441\u0442\u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043f\u0440\u0438\u0447\u0451\u043c \u043f\u043b\u0430\u0442\u043d\u043e. \u0418\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e \u0440\u0443\u0447\u043d\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0442\u0438\u043b\u0435\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0435\u0441\u043b\u0438 \u043d\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0439, \u0442\u043e \u0432\u0435\u0441\u044c\u043c\u0430 \u0442\u0440\u0443\u0434\u043e\u0451\u043c\u043a\u043e\u0439<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0431\u0443\u0434\u0443\u0447\u0438 \u043d\u0435\u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u044b\u043c, \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0444\u043e\u0440\u043a\u0430\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0441\u0432\u043e\u0439 \u043b\u0430\u0434<\/p>\n<\/li>\n<\/ol>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u0441\u0451 \u0436\u0435, \u043e\u0441\u043e\u0437\u043d\u0430\u0432\u0430\u044f \u044d\u0442\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f, \u0440\u0435\u0448\u0438\u043b\u0438\u0441\u044c \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u0432\u043e\u0435\u0433\u043e UI Kit, \u0442\u043e \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438 \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u0443\u0442\u0438.<\/p>\n<hr\/>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0435\u0451 \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/h3>\n<h4>\u0427\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c?<\/h4>\n<p>\u0415\u0441\u0442\u044c \u0434\u0432\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 UI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u043d\u0430 Angular:<\/p>\n<ol>\n<li>\n<p>\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Angular CLI. \u042d\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Workspace \u2013 \u043e\u0431\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 (\u0430\u043d\u0430\u043b\u043e\u0433 Solution \u0432 \u043c\u0438\u0440\u0435 .NET). \u041d\u043e \u0435\u0441\u043b\u0438 \u0432 Workspace \u0435\u0441\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0435\u0451 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442, \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0438\u0445 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0431\u0443\u0434\u0435\u0442 \u0432\u0435\u0441\u044c\u043c\u0430 \u043d\u0435\u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u043e<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <a href=\"https:\/\/nx.dev\/\" rel=\"noopener noreferrer nofollow\">Nx<\/a> \u0438 \u0435\u0433\u043e \u043c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432. \u0417\u0434\u0435\u0441\u044c  \u043f\u0440\u043e\u0449\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0441\u0432\u044f\u0437\u044c\u044e \u043c\u0435\u0436\u0434\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438, \u043e\u0434\u043d\u0430\u043a\u043e, \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u043e\u0439 \u043c\u0435\u0434\u0430\u043b\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u0430\u043c\u043e\u0433\u043e Nx<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0439\u0434\u0451\u043c \u043f\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u043c\u0443 \u0438 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438 \u2013 \u0441 Angular CLI \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u043c \u043f\u043e\u0434 \u043e\u0434\u0438\u043d \u043f\u0430\u043a\u0435\u0442. \u041c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043d\u0443\u0436\u043d\u044b \u0441\u043a\u043e\u0440\u0435\u0435 \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432, \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c\u044b\u0445 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u0418\u0442\u043e\u0433\u043e:<\/p>\n<ul>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c Angular CLI<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043f\u043e\u0434 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043d\u0451\u043c \u2013 Angular Workspace \u0441 \u043e\u0434\u043d\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u043d\u0430\u0448\u0438\u043c UI Kit<\/p>\n<\/li>\n<li>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 NPM Registry (\u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u043c \u0438\u043b\u0438 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u043c \u043f\u043e \u0442\u0438\u043f\u0443 Nexus \u0438\u043b\u0438 Verdaccio)<\/p>\n<\/li>\n<\/ul>\n<h4>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430<\/h4>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a <a href=\"https:\/\/angular.dev\/tools\/libraries\/creating-libraries\" rel=\"noopener noreferrer nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430<\/a> \u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 Angular (\u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u044d\u0442\u043e v19, \u0430 \u0432\u044b\u0445\u043e\u0434\u044f\u0449\u0430\u044f \u0432 \u043c\u0430\u0435 2025 \u0433\u043e\u0434\u0430 v20 \u0435\u0449\u0451 \u0431\u0443\u0434\u0435\u0442 \u043d\u0443\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u0430\u0442\u0447\u0430\u0445):<\/p>\n<pre><code>$ npx @angular\/cli@19 new ui-repo --no-create-application $ cd .\/ui-repo\/ $ npm run ng generate library @my\/ui-kit <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043a\u0430\u043a <code>@my\/ui-kit<\/code>. \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u043e\u0437\u0436\u0435, \u0435\u0441\u043b\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f.<\/p>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u043d\u0435 \u043e\u0434\u0438\u043d, \u043d\u043e \u0434\u0432\u0430 <code>package.json<\/code>: \u043e\u0434\u0438\u043d \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0432 <code>\/projects\/my\/ui-kit\/<\/code>. \u041f\u0435\u0440\u0432\u044b\u0439 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c\u0443 Workspace, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u043a \u0441\u0430\u043c\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435. \u041b\u044e\u0431\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u043e, \u0447\u0435\u0440\u0435\u0437 <code>npm i<\/code>, \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e Workspace.<\/p>\n<p>\u0412\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e <code>\/projects\/my\/ui-kit\/package.json<\/code>:<\/p>\n<pre><code class=\"json\">{   \"name\": \"@my\/ui-kit\",   \"version\": \"0.0.1\",   \"peerDependencies\": {     \"@angular\/common\": \"^19.2.0\",     \"@angular\/core\": \"^19.2.0\"   },   \"dependencies\": {     \"tslib\": \"^2.3.0\"   },   \"sideEffects\": false } <\/code><\/pre>\n<p>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u0435:<\/p>\n<ol>\n<li>\n<p><code>name<\/code> \u2013 \u044d\u0442\u043e \u043f\u043e\u0434 \u043a\u0430\u043a\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c \u043f\u0430\u043a\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 NPM Registry<\/p>\n<\/li>\n<li>\n<p><code>version<\/code> \u2013 \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u0430\u043a\u0435\u0442\u0430. \u0415\u0451 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0435\u0439, \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0443, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0430<\/p>\n<\/li>\n<li>\n<p><code>peerDependencies<\/code> \u2013 \u0441 \u043a\u0430\u043a\u0438\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 <code>@angular\/*<\/code> \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a (\u043d\u043e \u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e) \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u043f\u0430\u043a\u0435\u0442<\/p>\n<\/li>\n<li>\n<p><code>dependencies<\/code> \u2013 \u0442\u0440\u0430\u043d\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043f\u0430\u0434\u0443\u0442 \u0432 production<\/p>\n<\/li>\n<li>\n<p><code>sideEffects<\/code> \u2013 \u0444\u043b\u0430\u0433 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u043e\u0432, \u0432\u0440\u043e\u0434\u0435 WebPack \u0438\u043b\u0438 Vite, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c tree-shaking<\/p>\n<\/li>\n<\/ol>\n<p>\u041c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 Angular, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0432\u0435\u0440\u0441\u0438\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0432\u0430\u043c \u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0435\u0451 \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435, \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0435\u0451, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0443\u0436\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"json\">{   \"name\": \"@my\/ui-kit\",   \"version\": \"0.0.1\",   \"peerDependencies\": {     \"@angular\/common\": \"&gt;=19.2.0 &lt;21.0.0\",     \"@angular\/core\": \"&gt;=19.2.0 &lt;21.0.0\"   },   \"dependencies\": {     \"tslib\": \"^2.3.0\"   },   \"sideEffects\": false } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u0430 \u0441 Angular 19.2.0 \u0438 \u0434\u043e 21.0.0 (\u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e).<\/p>\n<h4>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0439 \u043f\u0430\u043a\u0435\u0442\u0430<\/h4>\n<p>\u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 <code>package.json<\/code>:<\/p>\n<pre><code class=\"json\">{   \"name\": \"ui-repo\",   \"version\": \"0.0.0\",   \"scripts\": {     \"ng\": \"ng\",     \"start\": \"ng serve\",     \"build\": \"ng build --configuration production @my\/ui-kit\",     \"watch\": \"ng build --watch --configuration development @my\/ui-kit\",     \"test\": \"ng test\",     \"release:patch\": \"cd .\/projects\/my\/ui-kit\/ &amp;&amp; npm version patch\",     \"release:minor\": \"cd .\/projects\/my\/ui-kit\/ &amp;&amp; npm version minor\",     \"release:major\": \"cd .\/projects\/my\/ui-kit\/ &amp;&amp; npm version major\"   },   \"private\": true,   \"dependencies\": {     \/\/ ...   },   \"devDependencies\": {    \/\/ ...   } } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0432 <code>\/projects\/my\/ui-kit\/package.json<\/code> \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e <a href=\"https:\/\/semver.org\/\" rel=\"noopener noreferrer nofollow\">semantic versioning<\/a>:<\/p>\n<pre><code>$ npm run release:patch # 0.0.1 -&gt; 0.0.2 $ npm run release:minor # 0.0.2 -&gt; 0.1.0 $ npm run release:major # 0.1.0 -&gt; 1.0.0 <\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u044d\u0442\u0438\u043c \u0441\u0442\u0430\u0432\u0438\u043b\u0441\u044f \u0438 \u0442\u044d\u0433 \u043d\u0430 \u043a\u043e\u043c\u043c\u0438\u0442\u0435 \u0432 git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0444\u043b\u0430\u0433 <code>--no-git-tag-version<\/code>.<\/p>\n<h4>\u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0435 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/h4>\n<p>\u0424\u0430\u0439\u043b <code>public-api.ts<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0438\u0437\u0432\u043d\u0435 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u041f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043e\u043d \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435:<\/p>\n<pre><code class=\"typescript\">\/*  * Public API Surface of ui-kit  *\/  export * from '.\/lib\/ui-kit.service'; export * from '.\/lib\/ui-kit.component'; <\/code><\/pre>\n<p>\u041b\u0443\u0447\u0448\u0435 \u043d\u0430\u043c \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u0432\u0441\u0451 \u0438\u0437 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 (\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u044b, \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0442\u0438\u043f\u044b \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435).<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u043f\u043e\u0434\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>\/ui-repo\/ \u251c\u2500\u2500 README.md \u251c\u2500\u2500 angular.json \u251c\u2500\u2500 package-lock.json \u251c\u2500\u2500 package.json \u251c\u2500\u2500 projects \u2502   \u2514\u2500\u2500 my \u2502       \u2514\u2500\u2500 ui-kit \u2502           \u251c\u2500\u2500 README.md \u2502           \u251c\u2500\u2500 ng-package.json \u2502           \u251c\u2500\u2500 package.json \u2502           \u251c\u2500\u2500 src \u2502           \u2502   \u251c\u2500\u2500 lib \u2502           \u2502   \u2502   \u251c\u2500\u2500 components \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 index.ts \u2502           \u2502   \u2502   \u2502   \u2514\u2500\u2500 ui-kit \u2502           \u2502   \u2502   \u2502       \u251c\u2500\u2500 index.ts \u2502           \u2502   \u2502   \u2502       \u251c\u2500\u2500 ui-kit.component.spec.ts \u2502           \u2502   \u2502   \u2502       \u2514\u2500\u2500 ui-kit.component.ts \u2502           \u2502   \u2502   \u2514\u2500\u2500 services \u2502           \u2502   \u2502       \u251c\u2500\u2500 index.ts \u2502           \u2502   \u2502       \u2514\u2500\u2500 ui-kit \u2502           \u2502   \u2502           \u251c\u2500\u2500 index.ts \u2502           \u2502   \u2502           \u251c\u2500\u2500 ui-kit.service.spec.ts \u2502           \u2502   \u2502           \u2514\u2500\u2500 ui-kit.service.ts \u2502           \u2502   \u2514\u2500\u2500 public-api.ts \u2502           \u251c\u2500\u2500 tsconfig.lib.json \u2502           \u251c\u2500\u2500 tsconfig.lib.prod.json \u2502           \u2514\u2500\u2500 tsconfig.spec.json \u2514\u2500\u2500 tsconfig.json <\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 <code>public-api.ts<\/code> \u0441\u0442\u0430\u043d\u0435\u0442 \u0442\u0430\u043a\u0438\u043c:<\/p>\n<pre><code class=\"typescript\">\/*  * Public API Surface of ui-kit  *\/  export * from '.\/lib\/components'; export * from '.\/lib\/services'; <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442.<\/p>\n<h3>\u041e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u0445<\/h3>\n<h4>Standalone vs NgModule<\/h4>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u2013 \u044d\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u0430 \u043b\u044e\u0431\u043e\u0433\u043e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e UI. \u041e\u043d\u0438 \u0435\u0441\u0442\u044c \u0432 React, Vue \u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0432 Angular. \u041e\u0434\u043d\u0430\u043a\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u043d\u044c\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0435\u0433\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0447\u0430\u0441\u0442\u044c\u044e <code>NgModule<\/code>, \u0431\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435\u043b\u044c\u0437\u044f \u0431\u044b\u043b\u043e \u0441\u0442\u0443\u043f\u0438\u0442\u044c \u0438 \u0448\u0430\u0433\u0443. \u041d\u043e \u0441 v14 \u0432\u0441\u0451 \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u043b\u043e\u0441\u044c: \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430 \u0438\u043b\u0438 \u043f\u0430\u0439\u043f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u044b \u043a <code>NgModule<\/code> (\u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 Standalone). \u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0436\u0435 \u043f\u043e\u0434\u0445\u043e\u0434.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u043d\u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u043c\u0438 UI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u043a\u0430\u043c\u0438 \u0434\u043b\u044f Angular, \u0442\u043e, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0437\u0430\u043c\u0435\u0447\u0430\u043b\u0438: \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u0439 <code>NgModule<\/code>. \u042d\u0442\u043e \u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u00ab<a href=\"https:\/\/sandroroth.com\/blog\/angular-shared-scam\/\" rel=\"noopener noreferrer nofollow\">SCAM-\u043f\u0430\u0442\u0442\u0435\u0440\u043d<\/a>\u00bb (Single Component Angular Module). \u0415\u0433\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043b\u0438, \u0447\u0442\u043e\u0431\u044b \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 tree-shaking: \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0448\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0430 \u043d\u0435 \u043e\u0434\u0438\u043d-\u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0451. \u0418 \u0440\u0430\u0437\u043c\u0435\u0440 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442\u0441\u044f.<\/p>\n<p>\u0421 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c Standalone-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0432 \u0442\u0430\u043a\u043e\u043c, \u0441\u043a\u0430\u0436\u0435\u043c \u043e\u0442\u043a\u0440\u043e\u0432\u0435\u043d\u043d\u043e, \u043a\u043e\u0441\u0442\u044b\u043b\u0435, \u043a\u0430\u043a SCAM-\u043f\u0430\u0442\u0442\u0435\u0440\u043d, \u043e\u0442\u043f\u0430\u043b\u0430, \u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0438\u0445 \u043e\u0431\u0451\u0440\u0442\u043e\u043a.<\/p>\n<p>\u0412 Angular \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445<\/p>\n<h4>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u043e\u043c<\/h4>\n<p>\u041e\u0431\u044b\u0447\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431: \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u043e \u0441\u0432\u043e\u0438\u043c\u0438 \u0441\u0442\u0438\u043b\u044f\u043c\u0438 \u0438 \u043b\u043e\u0433\u0438\u043a\u043e\u0439, \u0430 Angular \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 DOM-\u0434\u0435\u0440\u0435\u0432\u043e, \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 HTML-\u044d\u043b\u0435\u043c\u0435\u043d\u0442.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442:<\/p>\n<pre><code class=\"typescript\">import { Component } from '@angular\/core';  @Component({   selector: 'lib-ui-kit',   template: `     &lt;p&gt;       ui-kit works!     &lt;\/p&gt;   `, }) export class UiKitComponent {} <\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"xml\">&lt;lib-ui-kit&gt;   &lt;p&gt;     ui-kit works!   &lt;\/p&gt; &lt;\/lib-ui-kit&gt; <\/code><\/pre>\n<h4>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u043e\u043c\/\u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430<\/h4>\n<p>\u041c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u043f\u043e\u043b\u0435 <code>selector<\/code> \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u0430 <code>@Component<\/code> \u0432 \u0432\u0438\u0434\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0438\u043b\u0438 \u043f\u0441\u0435\u0432\u0434\u043e\u043a\u043b\u0430\u0441\u0441\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u00ab\u043d\u0430\u043d\u0438\u0437\u0430\u043d\u00bb \u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 HTML-\u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0438\u0439 \u0441\u043a\u0435\u043b\u0435\u0442\u043e\u043c (host-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c).<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442:<\/p>\n<pre><code class=\"typescript\">import { Component } from '@angular\/core';  @Component({   selector: '[framed-image]',   templateUrl: '.\/framed-image.component.html', }) export class FramedImageComponent { ... } <\/code><\/pre>\n<p>\u0412 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"xml\">&lt;div   framed-image=\"art-deco\"   src=\"somePainting.jpg\" \/&gt; <\/code><\/pre>\n<p>\u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441\u0442\u0440\u0430\u043d\u043d\u043e. \u041d\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0432\u0451\u0440\u0441\u0442\u043a\u0438.<\/p>\n<h4>\u0410 \u0432 \u0447\u0451\u043c \u0440\u0430\u0437\u043d\u0438\u0446\u0430?<\/h4>\n<p>\u041c\u044b \u043f\u0440\u0438\u0432\u044b\u043a\u043b\u0438 \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u2013 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e HTML-\u0448\u0430\u0431\u043b\u043e\u043d \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 code-behind. \u041d\u043e \u0441\u0442\u043e\u0438\u0442 \u0432\u0437\u0433\u043b\u044f\u043d\u0443\u0442\u044c \u0432 DevTools, \u0442\u043e \u0441\u0442\u0430\u043d\u0435\u0442 \u044f\u0441\u043d\u043e: Angular \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432 host-\u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u0447\u0442\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u0434\u043e\u0431\u043d\u043e.<\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u0441 Bootstrap <code>Navbar<\/code>. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u0448\u0430\u0431\u043b\u043e\u043d:<\/p>\n<pre><code class=\"xml\">&lt;ul class=\"navbar-nav mr-auto\"&gt;   &lt;li class=\"nav-item active\"&gt;     &lt;a class=\"nav-link\" href=\"#\"&gt;       Home &lt;span class=\"sr-only\"&gt;(current)&lt;\/span&gt;     &lt;\/a&gt;    &lt;\/li&gt;     &lt;li class=\"nav-item\"&gt;      &lt;a class=\"nav-link\" href=\"#\"&gt;       Link     &lt;\/a&gt;    &lt;\/li&gt; &lt;\/ul&gt; <\/code><\/pre>\n<p>\u0420\u0435\u0448\u0438\u0432 \u0434\u0435\u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u043d\u0430 Angular-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 <code>Navbar<\/code> \u0438 <code>Navlink<\/code> \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"xml\">&lt;navbar&gt;   &lt;navlink [active]=\"true\" href=\"#\"&gt;     Home &lt;span class=\"sr-only\"&gt;(current)&lt;\/span&gt;   &lt;\/navlink&gt;    &lt;navlink [active]=\"false\" href=\"#\"&gt;     Link   &lt;\/navlink&gt; &lt;\/navbar&gt; <\/code><\/pre>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e, \u0432 DOM-\u0434\u0435\u0440\u0435\u0432\u0435 \u044d\u0442\u043e \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u0432:<\/p>\n<pre><code class=\"xml\">&lt;navbar&gt;   &lt;ul class=\"navbar-nav mr-auto\"&gt;     &lt;navlink&gt;       &lt;li class=\"nav-item active\"&gt;         &lt;a class=\"nav-link\" href=\"#\"&gt;           Home &lt;span class=\"sr-only\"&gt;(current)&lt;\/span&gt;         &lt;\/a&gt;       &lt;\/li&gt;     &lt;\/navlink&gt;      &lt;navlink&gt;       &lt;li class=\"nav-item\"&gt;         &lt;a class=\"nav-link\" href=\"#\"&gt;           Link         &lt;\/a&gt;       &lt;\/li&gt;     &lt;\/navlink&gt;   &lt;\/ul&gt; &lt;\/navbar&gt; <\/code><\/pre>\n<p>\u041f\u043e \u0438\u0442\u043e\u0433\u0443 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043b\u0438\u0448\u043d\u0438\u0435 \u0443\u0440\u043e\u0432\u043d\u0438 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043c\u0430\u043b\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u044e\u0442 \u0441\u0442\u0438\u043b\u0438 \u0438 \u043b\u043e\u043c\u0430\u044e\u0442 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0432\u0451\u0440\u0441\u0442\u043a\u0443, \u0442\u0430\u043a, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043d\u0438\u043c\u0438, \u0435\u0449\u0451 \u0438 A11Y. \u0418 \u044d\u0442\u043e \u0435\u0449\u0451 \u043f\u043e\u043b\u0431\u0435\u0434\u044b.<\/p>\n<p>\u041f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, host-\u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u0435\u0441\u043b\u0438 \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440, \u0438\u043c\u0435\u0435\u0442 <code>display: inline<\/code>. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u0447\u043d\u043e \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440 \u0438\u043b\u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c tooltip. \u0425\u043e\u0442\u044c \u044d\u0442\u043e \u043d\u0435 \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u043e \u0442\u0430\u043a\u043e\u0439 host-\u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u043f\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0443 \u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u044b\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u043d \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442. \u0418 \u043d\u0430\u0448 tooltip \u043f\u043e \u0438\u0442\u043e\u0433\u0443 \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043d\u0435 \u0442\u0430\u043c, \u0433\u0434\u0435 \u0432\u044b \u043e\u0436\u0438\u0434\u0430\u043b\u0438&#8230;<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u043e\u0431\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u0430:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041f\u043e\u0434\u0445\u043e\u0434<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041f\u043b\u044e\u0441\u044b<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041c\u0438\u043d\u0443\u0441\u044b<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041d\u044e\u0430\u043d\u0441\u044b<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td rowspan=\"2\">\n<p align=\"left\">\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440       <\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0440\u043e\u0441\u0442\u043e\u0442\u0430 \u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0435<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041b\u0438\u0448\u043d\u044f\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c, \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 HTML-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e `display`, \u043e\u0442\u043b\u0438\u0447\u043d\u043e\u0435 \u043e\u0442 `inline`<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u042f\u0432\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e HTML-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">Host-\u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u0432\u043b\u0438\u044f\u0442\u044c \u043d\u0430 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 CSS, \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443 \u0438 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u043f\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u043c \u0441 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u043e\u043c<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<tr>\n<td rowspan=\"2\">\n<p align=\"left\">\u041d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\/\u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0411\u043e\u043b\u0435\u0435 \u0447\u0438\u0441\u0442\u0430\u044f \u0432\u0451\u0440\u0441\u0442\u043a\u0430 \u0438 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 CSS<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0423\u0441\u043b\u043e\u0436\u043d\u0435\u043d\u0438\u0435 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043d\u0435 \u043e\u0434\u043d\u0438\u043c, \u043d\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u043e\u0432<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043a\u0430\u043a-\u0442\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0434\u043b\u044f A11Y<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0434\u043b\u044f \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 HTML, \u0432\u0432\u0438\u0434\u0443 \u0447\u0435\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432<\/p>\n<\/td>\n<td>\n<p align=\"left\">\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u041a\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u2013 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0440\u0435\u0448\u0430\u0435\u043c\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0440\u044f\u0434 \u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u0430 \u2013 \u0438\u043a\u043e\u043d\u043a\u0443.<\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<\/h3>\n<h4>\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430, \u0430\u0441\u0441\u0435\u0442\u044b<\/h4>\n<p>\u0418\u043a\u043e\u043d\u043a\u0438 \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0434\u0435\u043b\u0430\u044e\u0442 \u0432 \u0432\u0438\u0434\u0435 SVG, \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438\u043b\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0448\u0440\u0438\u0444\u0442\u043e\u0432 \u0441 CSS. \u041c\u044b \u0432\u044b\u0431\u0435\u0440\u0435\u043c SVG \u2013 \u044d\u0442\u043e \u0437\u043e\u043b\u043e\u0442\u0430\u044f \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0430 \u043c\u0435\u0436\u0434\u0443 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c\u044e \u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u043e\u0439.<\/p>\n<p>\u0427\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u0442 \u0438\u043a\u043e\u043d\u043e\u043a \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435:<\/p>\n<ol>\n<li>\n<p>\u0418\u043a\u043e\u043d\u043a\u0438 \u2013 \u044d\u0442\u043e SVG<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u0438\u043a\u043e\u043d\u043a\u0438 \u0438\u043c\u0435\u044e\u0442 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u044b\u0435 \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0438\u043a\u043e\u043d\u043a\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u043f\u043e \u0441\u0435\u0442\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u0438\u043a\u043e\u043d\u043a\u0438 \u043f\u0440\u0435\u0434\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u0430 \u043d\u0435 \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e CDN<\/p>\n<\/li>\n<\/ol>\n<p>\u0423\u0447\u0438\u0442\u044b\u0432\u0430\u044f \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e\u0435, \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438\u043a\u043e\u043d\u043a\u0438:<\/p>\n<pre><code class=\"typescript\">import {   ChangeDetectionStrategy,   Component,   computed,   inject,   input, } from '@angular\/core';  import { IconLoaderService } from '..\/services';  \/**  * SVG-\u0438\u043a\u043e\u043d\u043a\u0430, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u0430\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435  *\/ @Component({   selector: 'lib-ui-icon',   template: `     &lt;svg       [attr.width]=\"size()\"       [attr.height]=\"size()\"     &gt;       &lt;use [attr.href]=\"iconLocation()\"&gt;&lt;\/use&gt;     &lt;\/svg&gt;   `,   styles: `     :host {       display: flex;     }   `,   changeDetection: ChangeDetectionStrategy.OnPush, }) export class IconComponent {   \/** \u0418\u043c\u044f \u0438\u043a\u043e\u043d\u043a\u0438 *\/   public readonly name = input&lt;string&gt;('');    \/** \u0420\u0430\u0437\u043c\u0435\u0440 \u0438\u043a\u043e\u043d\u043a\u0438 (px). \u041f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, `24` *\/   public readonly size = input&lt;number&gt;(24);    private readonly iconLoader = inject(IconLoaderService);    \/** \u041c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438\u043a\u043e\u043d\u043a\u0438 *\/   protected readonly iconLocation = computed&lt;string&gt;(() =&gt; {     const iconName = this.name();     return this.iconLoader.loadBuiltInIcon(iconName);   }); } <\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u0441\u0451 \u0437\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u043a\u0443 \u0430\u0441\u0441\u0435\u0442\u043e\u0432 \u0438 \u0438\u0445 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0432 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435. Angular \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u0445 \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443: \u043d\u0443\u0436\u043d\u043e \u043b\u0438\u0448\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u043a \u043d\u0438\u043c \u0432 \u0444\u0430\u0439\u043b\u0435 <code>ng-package.json<\/code>.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0431\u0435\u0440\u0451\u043c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Angular CLI \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e <code>\/assets\/<\/code>. \u0414\u0443\u043c\u0430\u044e, \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 SVG \u043f\u043e \u0441\u0435\u0442\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445 \u0432 \u0442\u0430\u043a\u043e\u043c \u0432\u0438\u0434\u0435 \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435, \u043c\u043e\u0436\u043d\u043e \u0438\u0445 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043f\u0440\u0430\u0439\u0442\u044b \u043f\u043e \u0433\u0440\u0443\u043f\u043f\u0430\u043c, \u043f\u0440\u0438\u0447\u0451\u043c \u043e\u0442\u0434\u0435\u043b\u0438\u043c \u0447\u0451\u0440\u043d\u043e-\u0431\u0435\u043b\u044b\u0435 \u043e\u0442 \u0446\u0432\u0435\u0442\u043d\u044b\u0445.<\/p>\n<p>\u0422\u043e\u0433\u0434\u0430 \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0441\u0442\u0430\u043d\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439:<\/p>\n<pre><code>\/ui-repo\/ \u251c\u2500\u2500 README.md \u251c\u2500\u2500 angular.json \u251c\u2500\u2500 package-lock.json \u251c\u2500\u2500 package.json \u251c\u2500\u2500 projects \u2502   \u2514\u2500\u2500 my \u2502       \u2514\u2500\u2500 ui-kit \u2502           \u251c\u2500\u2500 README.md \u2502           \u251c\u2500\u2500 ng-package.json \u2502           \u251c\u2500\u2500 package.json \u2502           \u251c\u2500\u2500 src \u2502           \u2502   \u251c\u2500\u2500 assets \u2502           \u2502   \u2502   \u2514\u2500\u2500 icons \u2502           \u2502   \u2502       \u251c\u2500\u2500 colorful \u2502           \u2502   \u2502       \u2502   \u251c\u2500\u2500 brands.svg \u2502           \u2502   \u2502       \u2502   \u2514\u2500\u2500 countries.svg \u2502           \u2502   \u2502       \u2514\u2500\u2500 monochrome \u2502           \u2502   \u2502           \u251c\u2500\u2500 brands.svg \u2502           \u2502   \u2502           \u2514\u2500\u2500 common.svg \u2502           \u2502   \u251c\u2500\u2500 lib \u2502           \u2502   \u2502   \u2514\u2500\u2500 components \u2502           \u2502   \u2502       \u251c\u2500\u2500 icon \u2502           \u2502   \u2502       \u2502   \u251c\u2500\u2500 components \u2502           \u2502   \u2502       \u2502   \u2502   \u251c\u2500\u2500 icon.component.ts \u2502           \u2502   \u2502       \u2502   \u2502   \u2514\u2500\u2500 index.ts \u2502           \u2502   \u2502       \u2502   \u2514\u2500\u2500 index.ts \u2502           \u2502   \u2502       \u2514\u2500\u2500 index.ts \u2502           \u2502   \u2514\u2500\u2500 public-api.ts \u2502           \u251c\u2500\u2500 tsconfig.lib.json \u2502           \u251c\u2500\u2500 tsconfig.lib.prod.json \u2502           \u2514\u2500\u2500 tsconfig.spec.json \u2514\u2500\u2500 tsconfig.json <\/code><\/pre>\n<p>\u0410 \u0444\u0430\u0439\u043b <code>ng-package.json<\/code> \u0438\u0437 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0442\u0430\u043a\u043e\u0433\u043e:<\/p>\n<pre><code class=\"json\">{   \"$schema\": \"..\/..\/..\/node_modules\/ng-packagr\/ng-package.schema.json\",   \"dest\": \"..\/..\/..\/dist\/my\/ui-kit\",   \"lib\": {     \"entryFile\": \"src\/public-api.ts\"   } } <\/code><\/pre>\n<p>\u0421\u0442\u0430\u043d\u0435\u0442 \u0442\u0430\u043a\u0438\u043c:<\/p>\n<pre><code class=\"json\">{   \"$schema\": \"..\/..\/..\/node_modules\/ng-packagr\/ng-package.schema.json\",   \"dest\": \"..\/..\/..\/dist\/my\/ui-kit\",   \"lib\": {     \"entryFile\": \"src\/public-api.ts\"   },   \"assets\": [     \"src\/assets\"   ] } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438 \u0441\u0431\u043e\u0440\u043a\u0435 (<code>npm run build<\/code>) \u0430\u0441\u0441\u0435\u0442\u044b \u043e\u043a\u0430\u0436\u0443\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043f\u043e \u043f\u0443\u0442\u0438 <code>\/dist\/my\/ui-kit\/src\/assets\/<\/code>.<\/p>\n<h4>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 SVG \u0447\u0435\u0440\u0435\u0437 \u0441\u043f\u0440\u0430\u0439\u0442\u044b<\/h4>\n<p>\u0421\u043f\u0440\u0430\u0439\u0442\u044b \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u2013 \u044d\u0442\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 SVG-\u0444\u0430\u0439\u043b, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 <code>&lt;symbol&gt;<\/code>, \u043a\u0430\u0436\u0434\u044b\u0439 \u0441 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c <code>id<\/code>. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0441\u043b\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u044d\u0442\u0438 <code>id<\/code> \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code>&lt;use&gt;<\/code> \u0432 \u043d\u0430\u0448\u0435\u043c <code>IconComponent<\/code>.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e <code>\/monochrome\/brands.svg<\/code> \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0434:<\/p>\n<pre><code class=\"xml\">&lt;svg height=\"0\" width=\"0\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" focusable=\"false\"&gt;   &lt;symbol id=\"mc__brands__telegram\" viewBox=\"0 0 24 24\"&gt;     &lt;g&gt;       &lt;path fill=\"currentColor\" d=\"...\" \/&gt;     &lt;\/g&gt;   &lt;\/symbol&gt;   &lt;symbol id=\"mc__brands__google\" viewBox=\"0 0 24 24\"&gt;     &lt;g&gt;       &lt;path fill=\"currentColor\" d=\"...\" \/&gt;     &lt;\/g&gt;   &lt;\/symbol&gt; &lt;\/svg&gt; <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c <code>IconLoaderService<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u043d\u0443\u0436\u043d\u044b\u0439 \u0441\u043f\u0440\u0430\u0439\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437, \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 DOM \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0438\u043a\u043e\u043d\u043a\u0443 (\u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u043b\u0443\u0447\u0448\u0435, \u043e \u0447\u0451\u043c \u0432\u044b \u043c\u0430\u044f\u043a\u043d\u0451\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445):<\/p>\n<pre><code class=\"typescript\">import { inject, Injectable, SecurityContext } from '@angular\/core'; import { DOCUMENT } from '@angular\/common'; import { HttpClient, HttpHeaders } from '@angular\/common\/http'; import { DomSanitizer } from '@angular\/platform-browser';  import { map, Observable, take, tap } from 'rxjs';  import { IconsMeta } from '..\/types';  \/**  * \u0421\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u043a\u043e\u043d\u043e\u043a  *\/ @Injectable({ providedIn: 'root' }) export class IconLoaderService {   private readonly httpClient = inject(HttpClient);   private readonly sanitizer = inject(DomSanitizer);   private readonly document = inject(DOCUMENT);    \/** \u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0446\u0432\u0435\u0442\u043d\u044b\u043c \u0438\u043a\u043e\u043d\u043a\u0430\u043c *\/   private readonly COLORFUL_ICONS_META: IconsMeta = {     prefix: 'clr',     directory: 'colorful',     sprites: [       'brands',       'countries',     ],   };    \/** \u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u043c\u043e\u043d\u043e\u0445\u0440\u043e\u043c\u043d\u044b\u043c \u0438\u043a\u043e\u043d\u043a\u0430\u043c *\/   private readonly MONOCHROME_ICONS_META: IconsMeta = {     prefix: 'mc',     directory: 'monochrome',     sprites: [       'brands',       'common',     ],   };    \/** \u0420\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c \u0432 \u0438\u043c\u0435\u043d\u0430\u0445 \u0438\u043a\u043e\u043d\u043e\u043a *\/   private readonly NAME_DELIMITER = '__';    \/**    * \u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 \u0438\u043a\u043e\u043d\u043a\u0443    *    * @param name - \u0418\u043c\u044f \u0438\u043a\u043e\u043d\u043a\u0438 \u043f\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u0435 `&lt;PREFIX&gt;__&lt;SPRITE&gt;__&lt;NAME&gt;`    * @returns \u041e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043a \u0438\u043a\u043e\u043d\u043a\u0435, \u0435\u0441\u043b\u0438 \u0438\u043c\u044f \u0438\u043a\u043e\u043d\u043a\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0444\u043e\u0440\u043c\u0443\u043b\u0435; \u0438\u043d\u0430\u0447\u0435 `''`. \u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u0441\u0430\u043c\u043e\u0439 \u0438\u043a\u043e\u043d\u043a\u0438 \u043f\u043e \u043f\u0443\u0442\u0438 \u043d\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f    *\/   public loadBuiltInIcon(name: string): string {     const isNameValid = this.isIconNameValid(name);     if (!isNameValid) {       return '';     }      const nameParts = name.split(this.NAME_DELIMITER);     const prefix = nameParts[0];     const sprite = nameParts[1];     let directory = '';      switch (prefix) {       case this.COLORFUL_ICONS_META.prefix: {         directory = this.COLORFUL_ICONS_META.directory;         break;       }        case this.MONOCHROME_ICONS_META.prefix: {         directory = this.MONOCHROME_ICONS_META.directory;         break;       }        default: {         break;       }     }      const iconPath = `#${name}`;     const spriteId = `svg__${prefix}__${sprite}`;      \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u043b\u0438 \u0441\u043f\u0440\u0430\u0439\u0442\u044b \u0432 DOM-\u0434\u0435\u0440\u0435\u0432\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043e\u0442\u043a\u0443\u0434\u0430 \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0442\u043e\u043c \u0438\u0437\u0432\u043b\u0435\u0447\u044c.     \/\/ \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f, \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0438 \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u043a\u0440\u044b\u0442\u044b\u0445 div-\u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0445     const spriteBlock = this.document.getElementById(spriteId);     if (!spriteBlock) {       this.loadIconSprite(spriteId, directory, sprite).subscribe();     }      return iconPath;   }    \/**    * \u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0441\u043f\u0440\u0430\u0439\u0442 \u0441 \u0433\u0440\u0443\u043f\u043f\u043e\u0439 \u0438\u043a\u043e\u043d\u043e\u043a    *    * @param id - \u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043f\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 \u0438\u043a\u043e\u043d\u043e\u043a    * @param sprite - \u0418\u043c\u044f \u0433\u0440\u0443\u043f\u043f\u044b \u0438\u043a\u043e\u043d\u043e\u043a    * @returns `Observable` \u0441 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u043c \u043e\u0431 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u043f\u0440\u0430\u0439\u0442\u0430    *\/   private loadIconSprite(id: string, directory: string, sprite: string): Observable&lt;void&gt; {     \/\/ \u0420\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u043c \u0433\u0440\u0443\u043f\u043f\u0443 \u0438\u043a\u043e\u043d\u043e\u043a \u0432 \u0441\u043a\u0440\u044b\u0442\u043e\u043c div, \u0438\u0437 \u043d\u0435\u0433\u043e \u0436\u0435 \u0438 \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u043a\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e     const spriteBlock = this.document.createElement('div');     spriteBlock.setAttribute('id', id);     spriteBlock.style.height = '0';     spriteBlock.style.width = '0';     this.document.body.insertBefore(spriteBlock, this.document.body.firstChild);      const spriteUrl = `public\/icons\/${directory}\/${sprite}.svg`;      return this.httpClient.get(`${window.location.origin}\/${spriteUrl}`, {         headers: new HttpHeaders().set('accept', 'image\/svg+xml'),         responseType: 'text'       })       .pipe(         take(1),         tap((response) =&gt; {           spriteBlock.innerHTML = this.sanitizer.sanitize(             SecurityContext.HTML,             this.sanitizer.bypassSecurityTrustHtml(response),           ) as string;         }),         map(() =&gt; undefined),       );   }    \/**    * \u0421\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u043b\u0438 \u0438\u043c\u044f \u0438\u043a\u043e\u043d\u043a\u0438 \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u0435 `&lt;PREFIX&gt;__&lt;SPRITE&gt;__&lt;NAME&gt;` \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u043c\u0438 \u0442\u0438\u043f\u0430\u043c\u0438 \u0438 \u0433\u0440\u0443\u043f\u043f\u0430\u043c\u0438 \u0438\u043a\u043e\u043d\u043e\u043a    *    * @param name - \u0418\u043c\u044f \u0438\u043a\u043e\u043d\u043a\u0438    * @returns `true`, \u0435\u0441\u043b\u0438 \u0438\u043c\u044f \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442; \u0438\u043d\u0430\u0447\u0435 `false`    *\/   private isIconNameValid(name: string): boolean {     const nameParts = name.split(this.NAME_DELIMITER);      \/\/ \u041b\u044e\u0431\u0430\u044f \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u0438\u043a\u043e\u043d\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u043c\u0435\u0442\u044c \u0438\u043c\u044f \u0438\u0437 3-\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442     if (nameParts.length &lt; 3) {       return false;     }      \/\/ \u041f\u0435\u0440\u0432\u0430\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0442\u0438\u043f \u0438\u043a\u043e\u043d\u043a\u0438     const iconType = nameParts[0];     if (iconType !== this.COLORFUL_ICONS_META.prefix &amp;&amp; iconType !== this.MONOCHROME_ICONS_META.prefix) {       return false;     }      \/\/ \u0412\u0442\u043e\u0440\u0430\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0433\u0440\u0443\u043f\u043f     const iconGroup = nameParts[1];     if (       (iconType === this.COLORFUL_ICONS_META.prefix &amp;&amp; !this.COLORFUL_ICONS_META.sprites.includes(iconGroup))       || (iconType === this.MONOCHROME_ICONS_META.prefix &amp;&amp; !this.MONOCHROME_ICONS_META.sprites.includes(iconGroup))     ) {       return false;     }      return true;   } } <\/code><\/pre>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e. \u041d\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043a\u0430\u043a \u043e\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0434\u0435\u043b\u0435.<\/p>\n<h3>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h3>\n<h4>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b<\/h4>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043d\u0430\u043c \u043d\u0435 \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u0431\u0435\u0437 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b:<\/p>\n<ol>\n<li>\n<p>Test runner, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043a\u0430\u043a \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u0442\u0430\u043a \u0438 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 CI\/CD. \u0412\u043c\u0435\u0441\u0442\u043e \u0431\u0435\u0437\u043d\u0430\u0434\u0451\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0435\u0439 Karma, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0435\u0449\u0451 \u0438 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f Jest<\/p>\n<\/li>\n<li>\n<p>Playground \u0434\u043b\u044f \u0432\u0438\u0442\u0440\u0438\u043d\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0418\u0437 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432: <a href=\"https:\/\/storybook.js.org\/\" rel=\"noopener noreferrer nofollow\">StoryBook<\/a> \u0438 <a href=\"https:\/\/ng-doc.com\/\" rel=\"noopener noreferrer nofollow\">NgDoc<\/a>. \u0421 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c, \u0443\u0432\u044b, \u0437\u0434\u0435\u0441\u044c \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. StoryBook \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043b\u0443\u0447\u0448\u0438\u043c \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442\u043e\u043c, \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u0435\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043b\u044f \u043d\u0430\u0441 \u0431\u043e\u043b\u0435\u0435, \u0447\u0435\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e (\u0445\u043e\u0442\u044c \u0438 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0431\u043e\u0440\u043e\u0442\u044c\u0441\u044f \u0441 \u0435\u0433\u043e React-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c\u044e)<\/p>\n<\/li>\n<\/ol>\n<h4>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c Jest<\/h4>\n<p>\u041f\u043e\u043a\u0430 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0438 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a \u043e\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b Angular \u0441 \u043d\u043e\u0432\u044b\u043c test runner \u043d\u0435\u0442, \u043d\u043e \u043d\u0435 \u0431\u0435\u0434\u0430. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f <a href=\"https:\/\/thymikee.github.io\/jest-preset-angular\/\" rel=\"noopener noreferrer nofollow\">jest-preset-angular<\/a>.<\/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>$ npm uninstall @types\/jasmine jasmine-core karma karma-chrome-launcher karma-coverage karma-jasmine karma-jasmine-html-reporter $ npm i -D jest jest-preset-angular @types\/jest ts-node <\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e <code>jest.config.ts<\/code> \u0432 \u043a\u043e\u0440\u043d\u0435, \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u0441 code coverage:<\/p>\n<pre><code class=\"typescript\">import type { Config } from 'jest'; import { createCjsPreset } from 'jest-preset-angular\/presets';  const config: Config = {   ...createCjsPreset(),   setupFilesAfterEnv: ['&lt;rootDir&gt;\/jest.setup.ts'],   rootDir: '.\/projects\/my\/ui-kit',   collectCoverage: true,   coverageDirectory: '&lt;rootDir&gt;\/..\/..\/..\/coverage',   coverageReporters: [     'clover',     'json',     'lcov',     'html'   ] };  export default config; <\/code><\/pre>\n<p>\u0424\u0430\u0439\u043b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f <code>\/projects\/my\/ui-kit\/jest.setup.ts<\/code>:<\/p>\n<pre><code class=\"typescript\">import { setupZoneTestEnv } from 'jest-preset-angular\/setup-env\/zone';  setupZoneTestEnv();  \/\/ Define global Mocks below <\/code><\/pre>\n<p>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0434\u043b\u044f Typescript \u0432 <code>\/projects\/my\/ui-kit\/tsconfig.spec.json<\/code>:<\/p>\n<pre><code class=\"typescript\">{   \"extends\": \"..\/..\/..\/tsconfig.json\",   \"compilerOptions\": {     \"outDir\": \"..\/..\/..\/out-tsc\/spec\",     \"module\": \"ES2022\",     \"types\": [\"jest\"]   },   \"include\": [     \"src\/**\/*.spec.ts\",     \"src\/**\/*.d.ts\"   ] } <\/code><\/pre>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c <code>package.json<\/code> \u0434\u043b\u044f 3-\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432:<\/p>\n<ol>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0441 \u043e\u0434\u043d\u043e\u043a\u0440\u0430\u0442\u043d\u044b\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c (<code>npm run test<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u0441 watch-\u0440\u0435\u0436\u0438\u043c\u043e\u043c (<code>npm run test:watch<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u0431\u043e\u0440\u043e\u0447\u043d\u043e\u043c \u0430\u0433\u0435\u043d\u0442\u0435 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 CI\/CD (<code>npm run test:ci<\/code>)<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"json\">{   \"name\": \"ui-repo\",   \"version\": \"0.0.0\",   \"scripts\": {     \"ng\": \"ng\",     \"start\": \"ng serve\",     \"build\": \"ng build --configuration production @my\/ui-kit\",     \"watch\": \"ng build --watch --configuration development @my\/ui-kit\",     \"test\": \"jest --maxWorkers=50%\",     \"test:ci\": \"jest ---detectOpenHandles\",     \"test:watch\": \"jest --watch --detectOpenHandles\"   },   \"private\": true,   \"dependencies\": {     \/\/ ...   },   \"devDependencies\": {     \/\/ ...   } } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u0440\u043e\u0433\u043d\u0430\u0442\u044c \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u0441\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"typescript\">import { ComponentRef } from '@angular\/core'; import { ComponentFixture, TestBed } from '@angular\/core\/testing'; import { provideHttpClient } from '@angular\/common\/http'; import { provideHttpClientTesting } from '@angular\/common\/http\/testing';  import { IconComponent } from '.\/icon.component';  describe('Icon', () =&gt; {   let component: IconComponent;   let componentRef: ComponentRef&lt;IconComponent&gt;;   let fixture: ComponentFixture&lt;IconComponent&gt;;    beforeEach(async () =&gt; {     await TestBed.configureTestingModule({       imports: [         IconComponent,       ],       providers: [         provideHttpClient(),         provideHttpClientTesting(),       ],     }).compileComponents();      fixture = TestBed.createComponent(IconComponent);     component = fixture.componentInstance;     componentRef = fixture.componentRef;      fixture.detectChanges();   })    it('\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f', () =&gt; {     expect(component).toBeTruthy();   }); }); <\/code><\/pre>\n<p>\u0418 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b:<\/p>\n<pre><code>$ npm run test  &gt; ui-repo@0.0.0 test &gt; jest --maxWorkers=50%   PASS  projects\/my\/ui-kit\/src\/lib\/components\/icon\/components\/icon.component.spec.ts   Icon     \u221a \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f (72 ms)  Test Suites: 1 passed, 1 total Tests:       1 passed, 1 total Snapshots:   0 total Time:        2.195 s, estimated 9 s Ran all test suites. <\/code><\/pre>\n<h4>StoryBook<\/h4>\n<p>StoryBook \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0438\u0437-\u0437\u0430 \u0441\u0432\u043e\u0435\u0439 React-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438, \u043d\u043e \u0432 \u0440\u043e\u043b\u0438 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u044b \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0432\u0438\u0442\u0440\u0438\u043d\u044b \u0432\u043f\u043e\u043b\u043d\u0435 \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u0442.<\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430:<\/p>\n<pre><code>$ npm create storybook@latest <\/code><\/pre>\n<p>\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u0441\u044f \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>compodoc<\/code> \u2013 \u0442\u0430\u043a \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u0443\u044e \u0438\u0437 \u0432\u0430\u0448\u0438\u0445 JSDoc-\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432.<\/p>\n<p>StoryBook \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0437\u043d\u0430\u043b \u043e \u043d\u0430\u0448\u0438\u0445 \u0438\u043a\u043e\u043d\u043a\u0430\u0445 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0430\u0441\u0441\u0435\u0442\u0430\u0445. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c <code>\/projects\/my\/ui-kit\/.storybook\/main.ts<\/code> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"typescript\">import type { StorybookConfig } from '@storybook\/angular';  const config: StorybookConfig = {   stories: [     '..\/src\/**\/*.mdx',     '..\/src\/**\/*.stories.@(js|jsx|mjs|ts|tsx)',   ],   addons: [     '@storybook\/addon-essentials',     '@storybook\/addon-onboarding',     '@storybook\/addon-interactions',   ],   framework: {     name: \"@storybook\/angular\",     options: {}   },   staticDirs: [     {       from: '..\/src\/assets',       to: '\/public',     }   ] };  export default config; <\/code><\/pre>\n<p>\u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b Angular-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0435 \u0432 StoryBook:<\/p>\n<pre><code class=\"typescript\">import { provideHttpClient } from '@angular\/common\/http';  import { applicationConfig } from '@storybook\/angular';  \/**  * \u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 StoryBook  *\/ export const StorybookModuleMeta = [   applicationConfig({     providers: [       provideHttpClient(),     ],   }), ]; <\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043b\u0438\u0448\u044c Story. \u042d\u0442\u043e \u0442\u0430\u043a\u0430\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u0438\u0433\u043e\u043d \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u0435\u043c\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>input()<\/code>. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0438\u0445 \u0434\u0432\u0435: \u043f\u0443\u0441\u043a\u0430\u0439 \u043e\u0434\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 playground, \u0430 \u0434\u0440\u0443\u0433\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0438\u043a\u043e\u043d\u043a\u0438:<\/p>\n<pre><code class=\"typescript\">import { StoryObj, Meta } from '@storybook\/angular';  import { StorybookModuleMeta } from '..\/..\/..\/..\/storybook-meta'; import { IconComponent } from '..\/components';  const meta: Meta&lt;typeof IconComponent&gt; = {   title: 'Components\/Icon',   component: IconComponent,   decorators: StorybookModuleMeta,   parameters: {     controls: {       exclude: ['iconLocation'],     },   }, };  export default meta;  type Story = StoryObj&lt;IconComponent&gt;; type UntypedStory = StoryObj;  export const Playground: Story = {   args: {     name: 'mc__common__cog',     size: 24,   }, };  export const AvailableIcons: UntypedStory = {   render: () =&gt; ({     template: `       &lt;div style=\"display: flex; flex-direction: column; margin: 1rem; width: 400px; height: 400px;\"&gt;         &lt;div style=\"display: flex; justify-content: space-between; margin-bottom: 1rem;\"&gt;           &lt;lib-ui-icon name=\"mc__brands__telegram\" \/&gt;           &lt;lib-ui-icon name=\"mc__brands__github\" \/&gt;           &lt;lib-ui-icon name=\"mc__brands__google\" \/&gt;           &lt;lib-ui-icon name=\"mc__common__bolt\" \/&gt;           &lt;lib-ui-icon name=\"mc__common__cog\" \/&gt;           &lt;lib-ui-icon name=\"mc__common__document\" \/&gt;         &lt;\/div&gt;          &lt;div style=\"display: flex; justify-content: space-between\"&gt;           &lt;lib-ui-icon name=\"clr__brands__windows\" \/&gt;           &lt;lib-ui-icon name=\"clr__brands__apple\" \/&gt;           &lt;lib-ui-icon name=\"clr__brands__android\" \/&gt;           &lt;lib-ui-icon name=\"clr__countries__germany\" \/&gt;           &lt;lib-ui-icon name=\"clr__countries__iceland\" \/&gt;           &lt;lib-ui-icon name=\"clr__countries__russia\" \/&gt;         &lt;\/div&gt;       &lt;\/div&gt;     `,   }) } <\/code><\/pre>\n<p>\u041c\u043e\u0436\u0435\u043c \u043e\u0446\u0435\u043d\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0432 StoryBook:<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/68394d2a6d3815ba950c4939\" data-style=\"\" id=\"68394d2a6d3815ba950c4939\" width=\"\"><\/div>\n<h3>\u041a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438<\/h3>\n<p>\u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c, \u043d\u0430\u0441 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. \u041d\u043e \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u2013 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d base HREF? \u0412 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0436\u0451\u0441\u0442\u043a\u043e \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u043a \u0430\u0441\u0441\u0435\u0442\u0430\u043c, \u043a\u0430\u043a \u0432 <code>IconLoaderService<\/code>, \u0443\u0436\u0435 \u043d\u0435 \u043f\u043e\u0434\u043e\u0439\u0434\u0443\u0442.<\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 <a href=\"https:\/\/angular.dev\/api\/core\/InjectionToken\" rel=\"noopener noreferrer nofollow\">InjectionToken<\/a>. \u041c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u043e\u043a\u0435\u043d \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0438\u0437\u0432\u043d\u0435 \u0438 \u0432\u043d\u0435\u0434\u0440\u0438\u0442\u044c \u0438\u0445 \u0432 \u043d\u0443\u0436\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>provideUiKitSettings()<\/code> \u0434\u043b\u044f \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u2013 \u043f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 <code>provideHttpClient()<\/code> \u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438:<\/p>\n<pre><code class=\"typescript\">import { InjectionToken, Provider } from '@angular\/core';  \/**  * \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 UI Kit  *\/ export type UiKitParams = {   \/** URL, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u043e\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 `\/` *\/   baseHref: string;    \/** \u0418\u043c\u044f \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0430\u0441\u0441\u0435\u0442\u044b *\/   assetsDirectory: string; };  \/** \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b UI Kit, \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0438\u0437\u0432\u043d\u0435 *\/ export const UI_KIT_PARAMS = new InjectionToken&lt;UiKitParams&gt;('UiKitParams');  \/**  * \u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0441\u0442\u0443\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0434\u043b\u044f `@my\/ui-kit`  *  * @returns \u041f\u0443\u0441\u0442\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0434\u043b\u044f \u0442\u043e\u043a\u0435\u043d\u0430 `UI_KIT_PARAMS`  *\/ export const provideUiKitEmptySettings = (): Provider =&gt; {   const config: UiKitParams = {     baseHref: '',     assetsDirectory: ''   };    return {     provide: UI_KIT_PARAMS,     useValue: config,   }; };  \/**  * \u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0434\u043b\u044f `@my\/ui-kit`  *  * @param config - \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438  * @returns \u0417\u0430\u0434\u0430\u043d\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0434\u043b\u044f \u0442\u043e\u043a\u0435\u043d\u0430 `UI_KIT_PARAMS`  *\/ export const provideUiKitSettings = (config: UiKitParams): Provider =&gt; ({   provide: UI_KIT_PARAMS,   useValue: config, }); <\/code><\/pre>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0435\u0449\u0451 \u0432\u044b\u043d\u0435\u0441\u0435\u043d \u0438 <code>assetsDirectory<\/code>? \u0412 Angular \u0434\u043e v18 \u0430\u0441\u0441\u0435\u0442\u044b \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u043b\u0438\u0441\u044c \u0432 <code>\/assets\/<\/code>, \u0432 \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0437\u0434\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 \u0432 <code>\/public\/<\/code>. \u041f\u043b\u044e\u0441, \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u043f\u0443\u0442\u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0441\u0432\u043e\u0438\u043c\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043b\u0443\u0447\u0448\u0435 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u043c.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u044d\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432 <code>IconLoaderService<\/code>:<\/p>\n<pre><code class=\"typescript\">import { inject, Injectable, SecurityContext } from '@angular\/core'; import { DOCUMENT } from '@angular\/common'; import { HttpClient, HttpHeaders } from '@angular\/common\/http'; import { DomSanitizer } from '@angular\/platform-browser';  import { map, Observable, take, tap } from 'rxjs';  import { IconsMeta } from '..\/types'; import { UI_KIT_PARAMS } from '..\/..\/..\/config';  \/**  * \u0421\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u043a\u043e\u043d\u043e\u043a  *\/ @Injectable({ providedIn: 'root' }) export class IconLoaderService {   \/\/ ...      private readonly libParams = inject(UI_KIT_PARAMS);    \/\/ ...    \/**    * \u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0441\u043f\u0440\u0430\u0439\u0442 \u0441 \u0433\u0440\u0443\u043f\u043f\u043e\u0439 \u0438\u043a\u043e\u043d\u043e\u043a    *    * @param id - \u0423\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043f\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 \u0438\u043a\u043e\u043d\u043e\u043a    * @param sprite - \u0418\u043c\u044f \u0433\u0440\u0443\u043f\u043f\u044b \u0438\u043a\u043e\u043d\u043e\u043a    * @returns `Observable` \u0441 \u0441\u0438\u0433\u043d\u0430\u043b\u043e\u043c \u043e\u0431 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u043f\u0440\u0430\u0439\u0442\u0430    *\/   private loadIconSprite(id: string, directory: string, sprite: string): Observable&lt;void&gt; {     \/\/ ...      const spriteUrl = `${this.libParams.assetsDirectory}\/icons\/${directory}\/${sprite}.svg`;     const baseHref = this.libParams.baseHref.length &gt; 0       ? `${this.libParams.baseHref}\/`       : '';      return this.httpClient.get(`${window.location.origin}\/${baseHref}${spriteUrl}`, {         headers: new HttpHeaders().set('accept', 'image\/svg+xml'),         responseType: 'text'       })       .pipe(         take(1),         tap((response) =&gt; {           spriteBlock.innerHTML = this.sanitizer.sanitize(             SecurityContext.HTML,             this.sanitizer.bypassSecurityTrustHtml(response),           ) as string;         }),         map(() =&gt; undefined),       );   } } <\/code><\/pre>\n<p>\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u0441\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f StoryBook, \u043f\u0440\u043e\u043a\u0438\u043d\u0443\u0432 \u0432 \u043d\u0435\u0433\u043e \u043d\u0430\u0448\u0443 <code>provideUiKitSettings()<\/code> \u0444\u0443\u043d\u043a\u0446\u0438\u044e. \u0418\u043d\u0430\u0447\u0435 \u043e\u043d \u043d\u0435 \u043d\u0430\u0439\u0434\u0451\u0442 \u043d\u0430\u0448 <code>InjectionToken<\/code> \u0438 \u0440\u0430\u043d\u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0432\u0448\u0438\u0435 Story \u0441\u043b\u043e\u043c\u0430\u044e\u0442\u0441\u044f. \u041a \u0442\u0435\u0441\u0442\u0430\u043c \u044d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f, \u043d\u043e \u0434\u043b\u044f \u043d\u0438\u0445 \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>provideUiKitEmptySettings()<\/code>.<\/p>\n<h3>\u041e\u0442\u043b\u0430\u0434\u043a\u0430 \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c<\/h3>\n<h4>\u0422\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u0441\u0435\u0439 \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0431\u044b\u043b\u043e \u0431\u044b \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0432 \u043a\u0430\u043a\u043e\u043c-\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0432 NPM Registry \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c, \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442, \u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u0434\u0440\u0443\u0433 \u043f\u0440\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0432\u0441\u043f\u043b\u044b\u0432\u0451\u0442 \u043e\u0448\u0438\u0431\u043a\u0430, \u0447\u0438\u043d\u0438\u0442\u044c \u0435\u0451 \u0438 \u0432\u044b\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0442\u0447 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u0443\u0434\u043e\u0431\u043d\u043e. \u0413\u043e\u0440\u0430\u0437\u0434\u043e \u043b\u0443\u0447\u0448\u0435 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u2013 \u0438 \u044d\u0442\u043e \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u043e.<\/p>\n<p>\u0421\u043f\u043e\u0441\u043e\u0431 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0441 WebPack, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u043a\u0438 Vite + ESBuild.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0432 watch-\u0440\u0435\u0436\u0438\u043c\u0435 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0430 \u043d\u0435\u0451 symlink. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0435\u0441\u0441\u0438\u044f\u0445 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u043d\u0430\u043c \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c:<\/p>\n<pre><code>$ npm run watch              # \u0421\u0435\u0441\u0441\u0438\u044f \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 1: \u0441\u0431\u043e\u0440\u043a\u0430 \u0432 watch-\u0440\u0435\u0436\u0438\u043c\u0435 $ npm link .\/dist\/my\/ui-kit\/ # \u0421\u0435\u0441\u0441\u0438\u044f \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 2: \u0441\u043e\u0437\u0434\u0430\u0451\u043c symlink \u043d\u0430 \u0441\u0431\u043e\u0440\u043a\u0443 \u043f\u043e\u0441\u043b\u0435 \u0435\u0451 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f <\/code><\/pre>\n<h4>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u043d\u0435\u0441\u0451\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 <code>angular.json<\/code> \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0430\u0441\u0441\u0435\u0442\u044b, \u0437\u0430\u043f\u0438\u0441\u0430\u0432 \u0432 <code>projects.&lt;PROJECT&gt;.architect.build.options.assets<\/code> \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"json\">{   \"glob\": \"**\/*\",   \"input\": \".\/node_modules\/@my\/ui-kit\/src\/assets\/\",   \"output\": \"public\" \/\/ \u0418\u043b\u0438 assets, \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 } <\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p>\u0412 <code>projects.&lt;PROJECT&gt;.architect.build.options<\/code> \u0434\u043e\u0431\u0430\u0432\u0438\u043c:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"json\">\"preserveSymlinks\": true <\/code><\/pre>\n<ol start=\"3\">\n<li>\n<p>\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u043c \u043a\u044d\u0448 CLI, \u0447\u0442\u043e\u0431\u044b HMR \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"json\">{   \"$schema\": \".\/node_modules\/@angular\/cli\/lib\/config\/schema.json\",   \"version\": 1,   \"newProjectRoot\": \"projects\",   \"projects\": {     \/\/ Projects definiton   },   \"cli\": {     \"cache\": {       \"enabled\": false     }   } } <\/code><\/pre>\n<h4>\u0421\u0432\u044f\u0437\u044b\u0432\u0430\u043d\u0438\u0435<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043a\u0430\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c:<\/p>\n<pre><code>$ npm link @my\/ui-kit <\/code><\/pre>\n<p>\u0412 <code>\/node_modules\/<\/code> \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0441\u0431\u043e\u0440\u043a\u0443 \u043d\u0430\u0448\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0438 \u043f\u0440\u0438 \u0432\u0441\u044f\u043a\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u0442\u044c \u0438\u0445 \u0438 \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0434\u043b\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432 <code>app.config.ts<\/code>:<\/p>\n<pre><code class=\"typescript\">import { ApplicationConfig, provideZoneChangeDetection } from '@angular\/core'; import { provideHttpClient } from '@angular\/common\/http'; import { provideRouter } from '@angular\/router';  import { provideUiKitSettings } from '@my\/ui-kit';  import { routes } from '.\/app.routes'; import { environment } from '..\/environments\/environment';  export const appConfig: ApplicationConfig = {   providers: [     provideZoneChangeDetection({ eventCoalescing: true }),     provideRouter(routes),     provideHttpClient(),     provideUiKitSettings({       baseHref: environment.baseHref,       assetsDirectory: environment.assetsDirectory,     })   ] }; <\/code><\/pre>\n<p>\u0418 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0430 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e \u0438 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 Story \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0438\u043a\u043e\u043d\u043a\u0430\u043c\u0438:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/\/post_images\/d10\/b87\/507\/d10b87507efac0f8b6fbe57785b5526f.png\" alt=\"\u0423\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0442\u0435\u0441\u0442 \u0441 \u0438\u043a\u043e\u043d\u043a\u0430\u043c\u0438\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/\/post_images\/d10\/b87\/507\/d10b87507efac0f8b6fbe57785b5526f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/\/post_images\/d10\/b87\/507\/d10b87507efac0f8b6fbe57785b5526f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0423\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0442\u0435\u0441\u0442 \u0441 \u0438\u043a\u043e\u043d\u043a\u0430\u043c\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u0432\u0441\u0435 \u0430\u0441\u0441\u0435\u0442\u044b \u043f\u043e\u0434\u0433\u0440\u0443\u0437\u0438\u043b\u0438\u0441\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e, \u043f\u0440\u0438\u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0430\u0448 <code>environment<\/code> \u0431\u044b\u043b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d \u0442\u0430\u043a:<\/p>\n<pre><code class=\"typescript\">export const environment = {   baseHref: '',   assetsDirectory: 'public', }; <\/code><\/pre>\n<p>\u0423\u0431\u0435\u0434\u0438\u043c\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0430\u0448\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u0437\u043c\u0435\u043d\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>baseHref<\/code> \u043d\u0430 <code>accounts<\/code>:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/\/post_images\/22c\/6eb\/d72\/22c6ebd72dbd30c4a4cfcad43fb02021.png\" alt=\"\u0423\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0442\u0435\u0441\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a: \u0438\u043a\u043e\u043d\u043a\u0438 \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/\/post_images\/22c\/6eb\/d72\/22c6ebd72dbd30c4a4cfcad43fb02021.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/\/post_images\/22c\/6eb\/d72\/22c6ebd72dbd30c4a4cfcad43fb02021.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0423\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u0442\u0435\u0441\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a: \u0438\u043a\u043e\u043d\u043a\u0438 \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f<\/figcaption><\/div>\n<\/figure>\n<p>\u0410\u0441\u0441\u0435\u0442\u044b \u043d\u0435 \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0432\u0448\u0435\u0433\u043e\u0441\u044f \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0433\u043e \u043f\u0443\u0442\u0438, \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0433\u043e \u0441 \u0442\u0435\u043c, \u0433\u0434\u0435 \u043e\u043d\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e. \u041f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u043e\u0435, \u043a\u0430\u043a\u043e\u0435 \u043c\u044b \u0438 \u043e\u0436\u0438\u0434\u0430\u043b\u0438.<\/p>\n<h3>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0444\u043e\u0440\u043c<\/h3>\n<p>Angular Forms \u2013 \u044d\u0442\u043e \u043d\u0435\u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u043c\u043e\u0449\u043d\u044b\u0439 \u043f\u0430\u043a\u0435\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 HTML-\u0444\u043e\u0440\u043c\u0430\u043c\u0438 \u0438 \u0438\u0445 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435. \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0444\u043e\u0440\u043c \u043f\u0440\u044f\u043c\u043e \u0432 \u043d\u0430\u0448\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>ControlValueAccessor<\/code>.<\/p>\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u043f\u0443\u0433\u0430\u044e\u0449\u0435\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435, \u0437\u0434\u0435\u0441\u044c \u0432\u0441\u0451 \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<ul>\n<li>\n<p><code>writeValue<\/code> \u2013 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 Angular \u0445\u043e\u0447\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 <code>FormControl<\/code>. \u042d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 <code>ngModel<\/code> \u0432 \u044f\u0432\u043d\u043e\u043c \u0432\u0438\u0434\u0435, \u043b\u0438\u0431\u043e \u0447\u0435\u0440\u0435\u0437 \u0444\u043e\u0440\u043c\u0443, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d <code>FormControl<\/code><\/p>\n<\/li>\n<li>\n<p><code>registerOnChange<\/code> \u2013 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 callback, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u0438\u0442\u044c \u043e\u0431 \u044d\u0442\u043e\u043c \u0444\u043e\u0440\u043c\u0443<\/p>\n<\/li>\n<li>\n<p><code>registerOnTouched<\/code> \u2013 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 callback, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u043e\u0431\u0449\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0435, \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0441 <code>FormControl<\/code> (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043b\u0438\u043a\u043d\u0443\u043b \u0438\u043b\u0438 \u0441\u0444\u043e\u043a\u0443\u0441\u0438\u0440\u043e\u0432\u0430\u043b\u0441\u044f)<\/p>\n<\/li>\n<li>\n<p><code>setDisabledState<\/code> \u2013 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 <code>FormControl<\/code>, \u043d\u0443\u0436\u043d\u043e \u043b\u0438 \u0435\u0433\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0451\u0445\u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u043b\u0430\u0436\u043e\u043a, checkbox, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>true<\/code>, <code>false<\/code> \u0438 <code>null<\/code>. \u0412\u043e\u0442 \u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 Angular Forms:<\/p>\n<pre><code class=\"typescript\">import {   Component,   forwardRef,   signal, } from '@angular\/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular\/forms';  \/**  * \u0424\u043b\u0430\u0436\u043e\u043a \u0441 \u0442\u0440\u0435\u043c\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c\u0438: `true`, `false` \u0438 `null`  *\/ @Component({   selector: '...',      \/\/ \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u043b\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 FormControl   \/\/ \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432 \u0441\u043e\u0441\u0442\u0430\u0432\u0435 Angular Forms \u0438 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c [(ngModel)]   providers: [     {       provide: NG_VALUE_ACCESSOR,       useExisting: forwardRef(() =&gt; TriCheckboxComponent),       multi: true,     },   ], }) export class TriCheckboxComponent implements ControlValueAccessor {   writeValue(val: boolean | null): void {     this.ngModelValue.set(val);   }    registerOnChange(fn: Function): void {     this.onModelChange = fn;   }    registerOnTouched(fn: Function): void {     this.onModelTouched = fn;   }    setDisabledState(val: boolean): void {     this.disabled.set(val);   }    \/** \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 `ngModel` *\/   private ngModelValue = signal&lt;boolean | null&gt;(null);    \/** \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0444\u043b\u0430\u0436\u043a\u0430 *\/   public readonly checkedValue = this.ngModelValue.asReadonly();    \/** \u041e\u0442\u043a\u043b\u044e\u0447\u0451\u043d \u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 *\/   private readonly disabled = signal&lt;boolean&gt;(false);    \/** \u0421\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u0444\u043e\u0440\u043c\u0435, \u0447\u0442\u043e `FormControl` \u0438\u0437\u043c\u0435\u043d\u0438\u043b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 (\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442 `ngModel`) *\/   private onModelChange: Function = () =&gt; {};    \/** \u0421\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u0444\u043e\u0440\u043c\u0435, \u0447\u0442\u043e `FormControl` \u0431\u044b\u043b \u0437\u0430\u0442\u0440\u043e\u043d\u0443\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c (\u0441\u0442\u0430\u0432\u0438\u0442 CSS-\u043a\u043b\u0430\u0441\u0441 `ng-touched` \u0432 \u0444\u043e\u0440\u043c\u0435) *\/   private onModelTouched: Function = () =&gt; {};    \/**    * \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u0444\u043b\u0430\u0436\u043e\u043a    *     * @param event \u2013 \u0421\u043e\u043f\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435    *\/   protected clickTriCheckbox(event: Event): void {     event.preventDefault();      if (this.disabled()) {         return;     }      this.toggleState();     this.onModelChange(this.checkedValue());     this.onModelTouched();   }    \/**    * \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0444\u043b\u0430\u0436\u043a\u0430    *\/   public toggleState(): void {     \/\/ \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u043e\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e \u0446\u0438\u043a\u043b\u0443 null-true-false     switch (this.checkedValue()) {         case true: {             this.ngModelValue.set(false);             break;         }          case false: {             this.ngModelValue.set(null);             break;         }          case null: {             this.ngModelValue.set(true);             break;         }          default: {             break;         }     }   } } <\/code><\/pre>\n<p>\u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0434\u043e\u043f\u0443\u0449\u0435\u043d\u0438\u0435 \u0432 \u0447\u0430\u0441\u0442\u0438 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438 \u2014 \u044d\u0442\u043e \u043e\u0431\u043e\u0431\u0449\u0451\u043d\u043d\u0430\u044f \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u043b\u044f callback <code>registerOnTouched<\/code> \u0438 <code>registerOnChange<\/code>.<\/p>\n<h3>\u0422\u0451\u043c\u043d\u0430\u044f \u0442\u0435\u043c\u0430 (Dark Mode)<\/h3>\n<h4>\u0418\u0434\u0435\u044f<\/h4>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0442\u0451\u043c\u043d\u0430\u044f \u0442\u0435\u043c\u0430 \u2013 \u044d\u0442\u043e \u0443\u0436\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u0435\u0451 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e, \u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u0441 \u0443\u0447\u0442\u043e\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 CSS, \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e:<\/p>\n<ol>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 CSS-\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0435 \u0441\u0442\u0438\u043b\u0438 \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>var()<\/code>. \u0422\u043e\u043b\u044c\u043a\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0439\u0442\u0435, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u043b\u0438 \u0432 \u0435\u0451 \u0438\u043c\u0435\u043d\u0438 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0430, \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 runtime<\/p>\n<\/li>\n<li>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 CSS-\u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>light-dark()<\/code> \u2013 \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u0434\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0441\u0432\u0435\u0442\u043b\u043e\u0439 \u0438 \u0442\u0451\u043c\u043d\u043e\u0439 \u0442\u0435\u043c\u044b \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e<\/p>\n<\/li>\n<li>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 <code>theme<\/code> \u043d\u0430 <code>&lt;html&gt;<\/code> \u0431\u0443\u0434\u0435\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0442\u0435\u043c\u043e\u0439. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 <code>color-scheme<\/code>, \u0447\u0442\u043e \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043a\u0430\u043a\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>light-dark()<\/code><\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0442\u0435\u043c\u0443 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0432\u044b\u0431\u043e\u0440 \u0432 <code>LocalStorage<\/code>, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0451 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 <code>APP_INITIALIZER<\/code> \u0442\u0435\u043c\u0430 \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u0434\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0435\u043d\u0438\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b (\u0447\u0435\u0440\u0435\u0437 <code>prefers-color-scheme<\/code>)<\/p>\n<\/li>\n<\/ol>\n<h4>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h4>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 CSS-\u0441\u0442\u0438\u043b\u0435\u0439 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"css\">\/* \u041d\u0430\u0431\u043e\u0440 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u0445 *\/ :root {   --btn-text-color: light-dark(white, rgb(46, 43, 43));   --btn-background-color: light-dark(rgb(11, 88, 160), rgb(20, 211, 195)); }  \/* \u0421\u0432\u0435\u0442\u043b\u0430\u044f \u0446\u0432\u0435\u0442\u043e\u0432\u0430\u044f \u0442\u0435\u043c\u0430: \u0434\u043b\u044f light-dark() \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 *\/ [theme=\"light\"] {   color-scheme: light; }  \/* \u0422\u0451\u043c\u043d\u0430\u044f \u0446\u0432\u0435\u0442\u043e\u0432\u0430\u044f \u0442\u0435\u043c\u0430: \u0434\u043b\u044f light-dark() \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0432\u0442\u043e\u0440\u043e\u0439 \u0430\u0433\u0440\u0443\u043c\u0435\u043d\u0442 \/ [theme=\"dark\"] {   color-scheme: dark; } <\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u044d\u0442\u0438 \u0441\u0442\u0438\u043b\u0438 \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435:<\/p>\n<pre><code class=\"typescript\">import { Component } from '@angular\/core';  \/**  * \u041e\u0431\u044b\u0447\u043d\u0430\u044f \u043a\u043d\u043e\u043f\u043a\u0430  *\/ @Component({   selector: 'button[lib-ui-button]',   template: `     &lt;ng-content \/&gt;   `,   styles: `     :host {       padding: 10px;       border: none;       border-radius: 2px;       color: var(--btn-text-color);       background-color: var(--btn-background-color);     }   `, }) export class ButtonComponent {   \/\/ ... } <\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c <code>enum<\/code> \u0441 \u0442\u0435\u043c\u0430\u043c\u0438:<\/p>\n<pre><code class=\"typescript\">\/**  * \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0430\u044f \u0442\u0435\u043c\u0430 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f  *\/ export enum Theme {   \/** \u0421\u0432\u0435\u0442\u043b\u0430\u044f *\/   Light = 'light',    \/** \u0422\u0451\u043c\u043d\u0430\u044f *\/   Dark = 'dark', } <\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0441\u0435\u0440\u0432\u0438\u0441 \u043f\u043e \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044e \u0442\u0435\u043c \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"typescript\">import { inject, Injectable } from '@angular\/core'; import { DOCUMENT } from '@angular\/common';  import { Theme } from '..\/..\/enums';  \/**  * \u0421\u0435\u0440\u0432\u0438\u0441 \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0442\u0435\u043c\u044b \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f  *\/ @Injectable({ providedIn: 'root' }) export class ThemeService {   private readonly document = inject(DOCUMENT);    \/** \u0410\u0442\u0440\u0438\u0431\u0443\u0442 \u0432 DOM \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u043c\u044b \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f *\/   private readonly THEME_ATTRIBUTE = 'theme';    \/** \u041a\u043b\u044e\u0447 \u0432 `LocalStorage`, \u0433\u0434\u0435 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u0430\u044f \u0442\u0435\u043c\u0430 *\/   private readonly STORAGE_KEY = 'ui-theme';    \/**    * \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u0442\u0435\u043c\u0435 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f    *\/   public initialize(): void {     const currentTheme = localStorage.getItem(this.STORAGE_KEY) as Theme;     if (currentTheme) {       this.applyTheme(currentTheme);       return;     }      const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;     const initialTheme = prefersDark       ? Theme.Dark       : Theme.Light;      this.applyTheme(initialTheme);   }    \/**    * \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u0443\u044e \u0442\u0435\u043c\u0443 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f    *    * @param theme - \u0422\u0438\u043f \u0442\u0435\u043c\u044b    *\/   public setTheme(theme: Theme): void {     this.applyTheme(theme);   }    \/**    * \u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0442\u0435\u043c\u0443 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f    *\/   public toggleTheme(): void {     const currentTheme = localStorage.getItem(this.STORAGE_KEY) as Theme ?? Theme.Light;     const newTheme = currentTheme === Theme.Light       ? Theme.Dark       : Theme.Light;      this.applyTheme(newTheme);   }    \/**    * \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0435\u043c\u0443 \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u044f    *    * @param theme - \u0422\u0438\u043f \u0442\u0435\u043c\u044b    *\/   private applyTheme(theme: Theme): void {     this.document.documentElement.removeAttribute(this.THEME_ATTRIBUTE);     this.document.documentElement.setAttribute(this.THEME_ATTRIBUTE, theme);     localStorage.setItem(this.STORAGE_KEY, theme);   } } <\/code><\/pre>\n<h4>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h4>\n<p>\u0427\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0442\u0435\u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442, \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u044d\u0442\u043e \u0432 StoryBook:<\/p>\n<ol>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u044b\u0437\u043e\u0432 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 <code>APP_INITIALIZER<\/code> \u0432 \u043c\u0435\u0442\u0430-\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"typescript\">import { provideHttpClient } from '@angular\/common\/http'; import { inject, provideAppInitializer } from '@angular\/core';  import { applicationConfig } from '@storybook\/angular';  import { ThemeService } from '.\/lib\/services'; import { provideUiKitSettings } from '.\/lib\/config';  \/**  * \u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 StoryBook  *\/ export const StorybookModuleMeta = [   applicationConfig({     providers: [       provideHttpClient(),       provideUiKitSettings({         baseHref: '',         assetsDirectory: 'public',       }),       provideAppInitializer(() =&gt; {         const themeSwitcher = inject(ThemeService);         themeSwitcher.initialize();       }),     ],   }), ]; <\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0438\u043b\u0438 \u0432 <code>angular.json<\/code>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0443\u0442\u044c \u043a \u0441\u0442\u0438\u043b\u044f\u043c \u0432 \u0440\u0430\u0437\u0434\u0435\u043b <code>projects.@my\/ui-kit.storybook.styles<\/code><\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0438 Story \u043a \u043d\u0435\u043c\u0443:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"typescript\">import { Component, inject } from '@angular\/core';  import { StoryObj, Meta } from '@storybook\/angular';  import { StorybookModuleMeta } from '..\/..\/..\/storybook-meta'; import { ThemeService } from '..\/..\/services'; import { ButtonComponent } from '.\/button.component';  @Component({   selector: 'app-demo',   template: `     &lt;button       lib-ui-button       (click)=\"toggle()\"     &gt;       Toggle theme   &lt;\/button&gt;   `,   imports: [     ButtonComponent,   ] }) class DemoComponent {   private readonly themeSwitcher = inject(ThemeService);    public toggle(): void {     this.themeSwitcher.toggleTheme();   } }  const meta: Meta&lt;typeof DemoComponent&gt; = {   title: 'Components\/Button',   component: DemoComponent,   decorators: StorybookModuleMeta, };  export default meta;  type Story = StoryObj&lt;DemoComponent&gt;;  export const Playground: Story = {}; <\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/68394d2b8f844fa824b61815\" data-style=\"\" id=\"68394d2b8f844fa824b61815\" width=\"\"><\/div>\n<h3>\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c (A11Y)<\/h3>\n<p>Accessibility\u2026 \u041a\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u0431\u043e\u043b\u0438 \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u043e\u0432\u0435.<br \/> \u0427\u0435\u0441\u0442\u043d\u043e, \u043c\u043d\u0435 \u043d\u0435 \u0434\u043e\u0432\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u0435\u0449\u0451 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0442\u044c \u043b\u044e\u0434\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0437\u0430\u0431\u0438\u0432\u0430\u044e\u0442 \u043d\u0430 \u043d\u0435\u0433\u043e \u043f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 web-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u0430. \u0422\u0435\u0441\u0442\u044b, \u0442\u043e\u0436\u0435 \u043c\u043d\u043e\u0433\u0438\u043c\u0438 \u043d\u0435\u043b\u044e\u0431\u0438\u043c\u044b\u0435, \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c, \u043f\u0438\u0448\u0435\u0442 \u043a\u0443\u0434\u0430 \u0431\u043e\u043b\u044c\u0448\u0435 \u043b\u044e\u0434\u0435\u0439, \u0447\u0435\u043c \u043c\u0443\u0447\u0430\u0435\u0442 \u0433\u043e\u043b\u043e\u0432\u0443 A11Y.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0432\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u043d\u0430\u043c, \u043f\u043e\u0440\u043e\u0439, \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430\u0440\u0443\u0448\u0430\u0442\u044c \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u0443\u044e HTML-\u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443, \u0432\u043b\u0438\u044f\u044e\u0449\u0443\u044e \u043d\u0430 A11Y: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0437\u0430\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b <code>table<\/code> \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0441\u0442\u0438, \u0433\u043e\u0440\u043e\u0434\u0438\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0441\u0432\u043e\u0451 \u0432\u0432\u0438\u0434\u0443 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0438\u0434 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e <code>&lt;input type=\"checkbox\" \/&gt;<\/code> \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0412\u0441\u0451 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0441\u0435\u0440\u044c\u0451\u0437\u043d\u043e \u043f\u043e\u0434\u043e\u0440\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u2013 \u043a\u0430\u043a \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u0438, \u0442\u0430\u043a \u0438 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u044d\u043a\u0440\u0430\u043d\u043d\u044b\u043c\u0438 \u0447\u0438\u0442\u0430\u043b\u043a\u0430\u043c\u0438, \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u043e\u0439 \u0438 \u043f\u0440\u043e\u0447\u0438\u043c.<\/p>\n<p>Angular \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0431\u0435\u0437 \u043e\u0441\u043e\u0431\u043e\u0433\u043e \u0443\u0449\u0435\u0440\u0431\u0430 \u0434\u043b\u044f A11Y. \u0412\u043e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439:<\/p>\n<ol>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435, \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043d\u044b\u0435 \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u044b, \u043a\u043e\u0433\u0434\u0430 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u0422\u0430\u043a \u0432 \u0438\u0437\u0431\u0435\u0433\u0430\u0435\u0442\u0435 \u043b\u0438\u0448\u043d\u0438\u0445 \u043e\u0431\u0451\u0440\u0442\u043e\u043a, \u0438 \u043d\u0435 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043b\u043e\u0432\u0443\u0448\u0435\u043a (\u0432\u0440\u043e\u0434\u0435 <code>ul &gt; lib-item &gt; li<\/code>)<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0435 \u0447\u0442\u043e-\u0442\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>&lt;input type=\"radio\" \/&gt;<\/code>), \u043f\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 HTML-\u044d\u043b\u0435\u043c\u0435\u043d\u0442 (<code>button<\/code>, <code>input<\/code>, <code>label<\/code>) \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432. \u042d\u0442\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u043e\u0439 \u0438 \u044d\u043a\u0440\u0430\u043d\u043d\u044b\u043c\u0438 \u0434\u0438\u043a\u0442\u043e\u0440\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0439\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c ARIA-\u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0435\u0441\u043b\u0438 \u0432\u044b \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435\u0441\u044c \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0432\u0451\u0440\u0441\u0442\u043a\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437 \u043e\u0434\u043d\u0438\u0445 <code>div<\/code> \u0441\u043e \u0441\u0442\u0438\u043b\u044f\u043c\u0438)<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u2013 \u0447\u0435\u0440\u0435\u0437 DevTools \u0438\u043b\u0438 \u043f\u0430\u043a\u0435\u0442 A11Y \u0438\u0437 \u0441\u043e\u0441\u0442\u0430\u0432\u0430 <code>@angular\/cdk<\/code><\/p>\n<\/li>\n<\/ol>\n<h3>\u0421\u0431\u043e\u0440\u043a\u0430 \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u043a\u0430\u043a NPM-\u043f\u0430\u043a\u0435\u0442 \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0443\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043b\u0438\u0442 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442, \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0435\u0433\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0448\u0430\u0433\u043e\u0432:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b <code>.npmrc<\/code> \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0431\u0440\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 <code>npm publish<\/code><\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 <code>.npmrc<\/code> \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>\/\/npm-registry.corp.com\/:token=abc123xyz @my:registry=https:\/\/npm-registry.corp.com\/ <\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u044e\u0449\u0438\u0439 <code>\/<\/code> \u2013 \u0431\u0435\u0437 \u043d\u0435\u0433\u043e NPM \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043f\u043e\u043d\u044f\u0442\u044c \u043f\u0443\u0442\u044c.<\/p>\n<p>\u0412\u0430\u043c \u0432 <code>.npmrc<\/code> \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u0443\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0444\u0430\u043a\u0442\u043e\u0440 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u043e\u043a\u0435\u043d, \u0438\u043b\u0438 basic-\u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f).<\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<pre><code>$ npm ci                        # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0442\u0440\u043e\u0433\u043e \u043f\u043e package-lock.json. \u0424\u0430\u0439\u043b \u0434\u043e\u043b\u0436\u0435\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438\u0438 $ npm run build                 # \u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 $ npm publish .\/dist\/my\/ui-kit\/ # \u041f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c <\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u0441\u043a\u0440\u0438\u043f\u0442 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043a\u0430\u043a \u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u0442\u0430\u043a \u0438 \u043d\u0430 \u0441\u0431\u043e\u0440\u043e\u0447\u043d\u043e\u043c \u0430\u0433\u0435\u043d\u0442\u0435 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 CI\/CD.<\/p>\n<hr\/>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041c\u044b \u043f\u0440\u043e\u0448\u043b\u0438 \u043f\u0443\u0442\u044c \u043e\u0442 \u043c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u0438 \u0434\u043e \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438, \u043e\u0445\u0432\u0430\u0442\u0438\u0432 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438 \u0441\u0442\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u044e, \u043d\u043e \u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u0441\u0431\u043e\u0440\u043a\u0443, \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e. \u0412\u0441\u0451 \u044d\u0442\u043e \u043d\u0435 \u0442\u0430\u043a \u0441\u043b\u043e\u0436\u043d\u043e, \u043a\u0430\u043a \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434. \u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u2013 \u043d\u0430\u0447\u0430\u0442\u044c, \u0430 \u0434\u0430\u043b\u044c\u0448\u0435 \u0432\u0441\u0451 \u043f\u043e\u0439\u0434\u0451\u0442 \u043a\u0443\u0434\u0430 \u043b\u0435\u0433\u0447\u0435.<\/p>\n<p>\u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u0432\u0430\u043c \u0432 \u0440\u0430\u0431\u043e\u0442\u0435.<\/p>\n<p>Happy coding! \ud83c\udf89<\/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\/914156\/\"> https:\/\/habr.com\/ru\/articles\/914156\/<\/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<p>\u0412\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441: \u043a\u0430\u043a \u0432\u0441\u0451 \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u043e, \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0438 \u0435\u0434\u0438\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e? \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u0441\u0451 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u043c \u2013 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 building block, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0430 \u0434\u0430\u043b\u044c\u0448\u0435 \u0447\u0435\u0440\u0435\u0434\u0443\u0439 \u0438\u043c\u0438 \u0438 \u0436\u043e\u043d\u0433\u043b\u0438\u0440\u0443\u0439, \u043a\u0430\u043a \u0434\u0443\u0448\u0435 \u0443\u0433\u043e\u0434\u043d\u043e. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043c\u043e\u0436\u043d\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0433\u043e\u0442\u043e\u0432\u044b\u0435 UI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0436\u0435 \u0432\u043b\u043e\u0436\u0435\u043d\u044b \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e-\u0447\u0430\u0441\u043e\u0432. \u041d\u043e, \u043f\u043e \u043c\u0435\u0440\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0451 \u043d\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, \u043f\u043e\u0440\u043e\u0439 \u0432\u0441\u0442\u0430\u044e\u0442 \u0432\u043e\u043f\u0440\u043e\u0441\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043e\u0431\u0443\u0436\u0434\u0430\u044e\u0442 \u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0441\u0432\u043e\u0435\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e UI Kit.<\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u043c, \u043c\u0443\u0442\u043e\u0440\u043d\u044b\u043c, \u0435\u0449\u0451 \u0438 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u043c \u0442\u0435\u0445\u0441\u0442\u0435\u043a\u0435. \u0423 Angular, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u0442\u044c \u0440\u0435\u043f\u0443\u0442\u0430\u0446\u0438\u044f \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430: \u043d\u0435 \u0441\u0430\u043c\u0430\u044f \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f, \u043d\u0435 \u043e\u0441\u043e\u0431\u043e \u0448\u0438\u0440\u043e\u043a\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e \u0438 \u043c\u0435\u043d\u044c\u0448\u0430\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u044c \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 React. \u041d\u0430 \u0434\u0435\u043b\u0435 \u0432\u0441\u0451 \u043d\u0435 \u0442\u0430\u043a \u0441\u0442\u0440\u0430\u0448\u043d\u043e. Angular \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0438 \u0443\u043b\u0443\u0447\u0448\u0430\u0435\u0442\u0441\u044f, \u043f\u0440\u0438\u0442\u043e\u043c, \u043a\u0430\u043a \u0438 \u0440\u0430\u043d\u044c\u0448\u0435, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 web-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>\u042f \u0441\u0447\u0438\u0442\u0430\u044e, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 Angular \u2013 \u044d\u0442\u043e \u043d\u0435 \u043f\u043e\u0434\u0432\u0438\u0433, \u0441\u043e\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0439 \u00ab\u0432\u043e\u043f\u0440\u0435\u043a\u0438\u00bb, \u043d\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u0440\u0430\u0437\u0443\u043c\u043d\u044b\u0439 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440, \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u043e\u0439\u0442\u0438 \u043a \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e.<\/p>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u2013 \u0441\u043a\u043e\u0440\u0435\u0435, \u043e\u0431\u0437\u043e\u0440 \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043e\u0442 \u00ab\u0437\u0430\u0447\u0435\u043c\u00bb \u0434\u043e \u00ab\u043a\u0430\u043a\u00bb, \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u043c\u0438.<\/p>\n<h3>\u0410 \u043a\u0430\u043a \u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u043e\u0435?<\/h3>\n<p>\u041c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0441\u0432\u043e\u0435\u0433\u043e UI Kit, \u043a\u043e\u0433\u0434\u0430 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0437\u0440\u0435\u043b\u044b\u0445 \u0438 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a. \u0410\u0432\u0442\u043e\u0440 \u044f\u0432\u043d\u043e \u043d\u0435 \u0441\u0442\u0440\u0430\u0434\u0430\u0435\u0442 \u0441\u0438\u043d\u0434\u0440\u043e\u043c\u043e\u043c NIH. \u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u0435\u0441\u0442\u044c \u0438\u0437 \u0447\u0435\u0433\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c: <a href=\"https:\/\/taiga-ui.dev\/\" rel=\"noopener noreferrer nofollow\">Taiga UI<\/a>, <a href=\"https:\/\/primeng.org\/\" rel=\"noopener noreferrer nofollow\">PrimeNG<\/a>, <a href=\"https:\/\/material.angular.dev\/\" rel=\"noopener noreferrer nofollow\">Angular Material<\/a> \u043e\u0442 \u0442\u043e\u0433\u043e \u0436\u0435 Google, \u043d\u0430\u043a\u043e\u043d\u0435\u0446.<\/p>\n<p>\u0422\u0430\u043a \u043f\u043e\u0447\u0435\u043c\u0443 \u0436\u0435 \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 UI Kit?<\/p>\n<ol>\n<li>\n<p>\u0412 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u0433\u043e \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c. \u0425\u043e\u0442\u0435\u043b\u0438 \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f, \u043d\u043e \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043b\u0438\u0431\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c Issue\/CR\/PR \u0430\u0432\u0442\u043e\u0440\u0430\u043c \u0438 \u0436\u0434\u0430\u0442\u044c, \u043d\u0430\u0434\u0435\u044f\u0441\u044c \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u043b\u0438\u0431\u043e \u0436\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0430\u043c\u043e\u043c\u0443<\/p>\n<\/li>\n<li>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0432\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043c\u043e\u0436\u0435\u0442 \u0432 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u043e\u0432\u0441\u0435 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0442\u044c \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u00ab\u043a\u043e\u0441\u0442\u044c\u044e \u0432 \u0433\u043e\u0440\u043b\u0435\u00bb, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0442\u0430\u043d\u0435\u0442 \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 \u043d\u043e\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 Angular<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043f\u043e\u0434\u0442\u044f\u0433\u0438\u0432\u0430\u044e\u0442 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b \u0441 \u0432\u0430\u0448\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0438\u043b\u0438 \u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0432\u0430\u0441 \u043f\u043e \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u0438\u043d\u044b\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0432\u0430\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u2013 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c (A11Y) \u0438\u043b\u0438 \u0442\u0451\u043c\u043d\u0443\u044e \u0442\u0435\u043c\u0443 (Dark Mode)<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0445 (\u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0430\u043b\u044c\u0446\u0435\u043c \u043d\u0430 PrimeNG) \u0442\u0435\u043c\u044b \u0438 \u0441\u0442\u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043f\u0440\u0438\u0447\u0451\u043c \u043f\u043b\u0430\u0442\u043d\u043e. \u0418\u0437-\u0437\u0430 \u044d\u0442\u043e\u0433\u043e \u0440\u0443\u0447\u043d\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0442\u0438\u043b\u0435\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0435\u0441\u043b\u0438 \u043d\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0439, \u0442\u043e \u0432\u0435\u0441\u044c\u043c\u0430 \u0442\u0440\u0443\u0434\u043e\u0451\u043c\u043a\u043e\u0439<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u0431\u0443\u0434\u0443\u0447\u0438 \u043d\u0435\u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u044b\u043c, \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0444\u043e\u0440\u043a\u0430\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0441\u0432\u043e\u0439 \u043b\u0430\u0434<\/p>\n<\/li>\n<\/ol>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u0441\u0451 \u0436\u0435, \u043e\u0441\u043e\u0437\u043d\u0430\u0432\u0430\u044f \u044d\u0442\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f, \u0440\u0435\u0448\u0438\u043b\u0438\u0441\u044c \u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0441\u0432\u043e\u0435\u0433\u043e UI Kit, \u0442\u043e \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0432\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438 \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438 \u043c\u043e\u0433\u0443\u0442 \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u0443\u0442\u0438.<\/p>\n<hr\/>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0435\u0451 \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/h3>\n<h4>\u0427\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c?<\/h4>\n<p>\u0415\u0441\u0442\u044c \u0434\u0432\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 UI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u043d\u0430 Angular:<\/p>\n<ol>\n<li>\n<p>\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Angular CLI. \u042d\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Workspace \u2013 \u043e\u0431\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 (\u0430\u043d\u0430\u043b\u043e\u0433 Solution \u0432 \u043c\u0438\u0440\u0435 .NET). \u041d\u043e \u0435\u0441\u043b\u0438 \u0432 Workspace \u0435\u0441\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0435\u0451 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442, \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0438\u0445 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0431\u0443\u0434\u0435\u0442 \u0432\u0435\u0441\u044c\u043c\u0430 \u043d\u0435\u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u043e<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <a href=\"https:\/\/nx.dev\/\" rel=\"noopener noreferrer nofollow\">Nx<\/a> \u0438 \u0435\u0433\u043e \u043c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432. \u0417\u0434\u0435\u0441\u044c  \u043f\u0440\u043e\u0449\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0441\u0432\u044f\u0437\u044c\u044e \u043c\u0435\u0436\u0434\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438, \u043e\u0434\u043d\u0430\u043a\u043e, \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u043e\u0439 \u043c\u0435\u0434\u0430\u043b\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u0430\u043c\u043e\u0433\u043e Nx<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u043f\u043e\u0439\u0434\u0451\u043c \u043f\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u043c\u0443 \u0438 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438 \u2013 \u0441 Angular CLI \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u043c \u043f\u043e\u0434 \u043e\u0434\u0438\u043d \u043f\u0430\u043a\u0435\u0442. \u041c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043d\u0443\u0436\u043d\u044b \u0441\u043a\u043e\u0440\u0435\u0435 \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432, \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u043c\u044b\u0445 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u0418\u0442\u043e\u0433\u043e:<\/p>\n<ul>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c Angular CLI<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043f\u043e\u0434 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043d\u0451\u043c \u2013 Angular Workspace \u0441 \u043e\u0434\u043d\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c, \u043d\u0430\u0448\u0438\u043c UI Kit<\/p>\n<\/li>\n<li>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 NPM Registry (\u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u043c \u0438\u043b\u0438 \u043a\u043e\u0440\u043f\u043e\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u043c \u043f\u043e \u0442\u0438\u043f\u0443 Nexus \u0438\u043b\u0438 Verdaccio)<\/p>\n<\/li>\n<\/ul>\n<h4>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430<\/h4>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a <a href=\"https:\/\/angular.dev\/tools\/libraries\/creating-libraries\" rel=\"noopener noreferrer nofollow\">\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430<\/a> \u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 Angular (\u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 \u044d\u0442\u043e v19, \u0430 \u0432\u044b\u0445\u043e\u0434\u044f\u0449\u0430\u044f \u0432 \u043c\u0430\u0435 2025 \u0433\u043e\u0434\u0430 v20 \u0435\u0449\u0451 \u0431\u0443\u0434\u0435\u0442 \u043d\u0443\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u0430\u0442\u0447\u0430\u0445):<\/p>\n<pre><code>$ npx @angular\/cli@19 new ui-repo --no-create-application $ cd .\/ui-repo\/ $ npm run ng generate library @my\/ui-kit <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043a\u0430\u043a <code>@my\/ui-kit<\/code>. \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u043e\u0437\u0436\u0435, \u0435\u0441\u043b\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f.<\/p>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u043d\u0435 \u043e\u0434\u0438\u043d, \u043d\u043e \u0434\u0432\u0430 <code>package.json<\/code>: \u043e\u0434\u0438\u043d \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0432 <code>\/projects\/my\/ui-kit\/<\/code>. \u041f\u0435\u0440\u0432\u044b\u0439 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c\u0443 Workspace, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u043a \u0441\u0430\u043c\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435. \u041b\u044e\u0431\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u043e, \u0447\u0435\u0440\u0435\u0437 <code>npm i<\/code>, \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e Workspace.<\/p>\n<p>\u0412\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e <code>\/projects\/my\/ui-kit\/package.json<\/code>:<\/p>\n<pre><code class=\"json\">{   \"name\": \"@my\/ui-kit\",   \"version\": \"0.0.1\",   \"peerDependencies\": {     \"@angular\/common\": \"^19.2.0\",     \"@angular\/core\": \"^19.2.0\"   },   \"dependencies\": {     \"tslib\": \"^2.3.0\"   },   \"sideEffects\": false } <\/code><\/pre>\n<p>\u041f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u0435:<\/p>\n<ol>\n<li>\n<p><code>name<\/code> \u2013 \u044d\u0442\u043e \u043f\u043e\u0434 \u043a\u0430\u043a\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c \u043f\u0430\u043a\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 NPM Registry<\/p>\n<\/li>\n<li>\n<p><code>version<\/code> \u2013 \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u0430\u043a\u0435\u0442\u0430. \u0415\u0451 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u0434 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0435\u0439, \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0443, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u0432 \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0430<\/p>\n<\/li>\n<li>\n<p><code>peerDependencies<\/code> \u2013 \u0441 \u043a\u0430\u043a\u0438\u043c\u0438 \u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438 <code>@angular\/*<\/code> \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a (\u043d\u043e \u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e) \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c \u043f\u0430\u043a\u0435\u0442<\/p>\n<\/li>\n<li>\n<p><code>dependencies<\/code> \u2013 \u0442\u0440\u0430\u043d\u0437\u0438\u0442\u0438\u0432\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043f\u0430\u0434\u0443\u0442 \u0432 production<\/p>\n<\/li>\n<li>\n<p><code>sideEffects<\/code> \u2013 \u0444\u043b\u0430\u0433 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u043e\u0432, \u0432\u0440\u043e\u0434\u0435 WebPack \u0438\u043b\u0438 Vite, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c tree-shaking<\/p>\n<\/li>\n<\/ol>\n<p>\u041c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 Angular, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0432\u0435\u0440\u0441\u0438\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0432\u0430\u043c \u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0435\u0451 \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435, \u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0435\u0451, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0443\u0436\u0435 \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"json\">{   \"name\": \"@my\/ui-kit\",   \"version\": \"0.0.1\",   \"peerDependencies\": {     \"@angular\/common\": \"&gt;=19.2.0 &lt;21.0.0\",     \"@angular\/core\": \"&gt;=19.2.0 &lt;21.0.0\"   },   \"dependencies\": {     \"tslib\": \"^2.3.0\"   },   \"sideEffects\": false } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u0430 \u0441 Angular 19.2.0 \u0438 \u0434\u043e 21.0.0 (\u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e).<\/p>\n<h4>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0439 \u043f\u0430\u043a\u0435\u0442\u0430<\/h4>\n<p>\u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u044e, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 <code>package.json<\/code>:<\/p>\n<pre><code class=\"json\">{   \"name\": \"ui-repo\",   \"version\": \"0.0.0\",   \"scripts\": {     \"ng\": \"ng\",     \"start\": \"ng serve\",     \"build\": \"ng build --configuration production @my\/ui-kit\",     \"watch\": \"ng build --watch --configuration development @my\/ui-kit\",     \"test\": \"ng test\",     \"release:patch\": \"cd .\/projects\/my\/ui-kit\/ &amp;&amp; npm version patch\",     \"release:minor\": \"cd .\/projects\/my\/ui-kit\/ &amp;&amp; npm version minor\",     \"release:major\": \"cd .\/projects\/my\/ui-kit\/ &amp;&amp; npm version major\"   },   \"private\": true,   \"dependencies\": {     \/\/ ...   },   \"devDependencies\": {    \/\/ ...   } } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0432 <code>\/projects\/my\/ui-kit\/package.json<\/code> \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e <a href=\"https:\/\/semver.org\/\" rel=\"noopener noreferrer nofollow\">semantic versioning<\/a>:<\/p>\n<pre><code>$ npm run release:patch # 0.0.1 -&gt; 0.0.2 $ npm run release:minor # 0.0.2 -&gt; 0.1.0 $ npm run release:major # 0.1.0 -&gt; 1.0.0 <\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u044d\u0442\u0438\u043c \u0441\u0442\u0430\u0432\u0438\u043b\u0441\u044f \u0438 \u0442\u044d\u0433 \u043d\u0430 \u043a\u043e\u043c\u043c\u0438\u0442\u0435 \u0432 git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0444\u043b\u0430\u0433 <code>--no-git-tag-version<\/code>.<\/p>\n<h4>\u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0435 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/h4>\n<p>\u0424\u0430\u0439\u043b <code>public-api.ts<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u043a\u0430\u043a\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0438\u0437\u0432\u043d\u0435 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u041f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043e\u043d \u0438\u043c\u0435\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435:<\/p>\n<pre><code class=\"typescript\">\/*  * Public API Surface of ui-kit  *\/  export * from '.\/lib\/ui-kit.service'; export * from '.\/lib\/ui-kit.component'; <\/code><\/pre>\n<p>\u041b\u0443\u0447\u0448\u0435 \u043d\u0430\u043c \u043f\u043e\u0434\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u0432\u0441\u0451 \u0438\u0437 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 (\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u044b, \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0442\u0438\u043f\u044b \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435).<\/p>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u043f\u043e\u0434\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>\/ui-repo\/ \u251c\u2500\u2500 README.md \u251c\u2500\u2500 angular.json \u251c\u2500\u2500 package-lock.json \u251c\u2500\u2500 package.json \u251c\u2500\u2500 projects \u2502   \u2514\u2500\u2500 my \u2502       \u2514\u2500\u2500 ui-kit \u2502           \u251c\u2500\u2500 README.md \u2502           \u251c\u2500\u2500 ng-package.json \u2502           \u251c\u2500\u2500 package.json \u2502           \u251c\u2500\u2500 src \u2502           \u2502   \u251c\u2500\u2500 lib \u2502           \u2502   \u2502   \u251c\u2500\u2500 components \u2502           \u2502   \u2502   \u2502   \u251c\u2500\u2500 index.ts \u2502           \u2502   \u2502   \u2502   \u2514\u2500\u2500 ui-kit \u2502           \u2502   \u2502   \u2502       \u251c\u2500\u2500 index.ts \u2502           \u2502   \u2502   \u2502       \u251c\u2500\u2500 ui-kit.component.spec.ts \u2502           \u2502   \u2502   \u2502       \u2514\u2500\u2500 ui-kit.component.ts \u2502           \u2502   \u2502   \u2514\u2500\u2500 services \u2502           \u2502   \u2502       \u251c\u2500\u2500 index.ts \u2502           \u2502   \u2502       \u2514\u2500\u2500 ui-kit \u2502           \u2502   \u2502           \u251c\u2500\u2500 index.ts \u2502           \u2502   \u2502           \u251c\u2500\u2500 ui-kit.service.spec.ts \u2502           \u2502   \u2502           \u2514\u2500\u2500 ui-kit.service.ts \u2502           \u2502   \u2514\u2500\u2500 public-api.ts \u2502           \u251c\u2500\u2500 tsconfig.lib.json \u2502           \u251c\u2500\u2500 tsconfig.lib.prod.json \u2502           \u2514\u2500\u2500 tsconfig.spec.json \u2514\u2500\u2500 tsconfig.json <\/code><\/pre>\n<p>\u0422\u043e\u0433\u0434\u0430 <code>public-api.ts<\/code> \u0441\u0442\u0430\u043d\u0435\u0442 \u0442\u0430\u043a\u0438\u043c:<\/p>\n<pre><code class=\"typescript\">\/*  * Public API Surface of ui-kit  *\/  export * from '.\/lib\/components'; export * from '.\/lib\/services'; <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442.<\/p>\n<h3>\u041e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u0445<\/h3>\n<h4>Standalone vs NgModule<\/h4>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u2013 \u044d\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u0430 \u043b\u044e\u0431\u043e\u0433\u043e \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e UI. \u041e\u043d\u0438 \u0435\u0441\u0442\u044c \u0432 React, Vue \u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0432 Angular. \u041e\u0434\u043d\u0430\u043a\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u043d\u044c\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0435\u0433\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0447\u0430\u0441\u0442\u044c\u044e <code>NgModule<\/code>, \u0431\u0435\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435\u043b\u044c\u0437\u044f \u0431\u044b\u043b\u043e \u0441\u0442\u0443\u043f\u0438\u0442\u044c \u0438 \u0448\u0430\u0433\u0443. \u041d\u043e \u0441 v14 \u0432\u0441\u0451 \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u043b\u043e\u0441\u044c: \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430 \u0438\u043b\u0438 \u043f\u0430\u0439\u043f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u044b \u043a <code>NgModule<\/code> (\u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0435 Standalone). \u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0436\u0435 \u043f\u043e\u0434\u0445\u043e\u0434.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u043d\u0435\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u043c\u0438 UI-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u043a\u0430\u043c\u0438 \u0434\u043b\u044f Angular, \u0442\u043e, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0437\u0430\u043c\u0435\u0447\u0430\u043b\u0438: \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u0439 <code>NgModule<\/code>. \u042d\u0442\u043e \u0442\u0430\u043a \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u00ab<a href=\"https:\/\/sandroroth.com\/blog\/angular-shared-scam\/\" rel=\"noopener noreferrer nofollow\">SCAM-\u043f\u0430\u0442\u0442\u0435\u0440\u043d<\/a>\u00bb (Single Component Angular Module). \u0415\u0433\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u043b\u0438, \u0447\u0442\u043e\u0431\u044b \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 tree-shaking: \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0448\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u0430 \u043d\u0435 \u043e\u0434\u0438\u043d-\u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0451. \u0418 \u0440\u0430\u0437\u043c\u0435\u0440 \u0438\u0442\u043e\u0433\u043e\u0432\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442\u0441\u044f.<\/p>\n<p>\u0421 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0435\u043c Standalone-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u0432 \u0442\u0430\u043a\u043e\u043c, \u0441\u043a\u0430\u0436\u0435\u043c \u043e\u0442\u043a\u0440\u043e\u0432\u0435\u043d\u043d\u043e, \u043a\u043e\u0441\u0442\u044b\u043b\u0435, \u043a\u0430\u043a SCAM-\u043f\u0430\u0442\u0442\u0435\u0440\u043d, \u043e\u0442\u043f\u0430\u043b\u0430, \u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0438\u0445 \u043e\u0431\u0451\u0440\u0442\u043e\u043a.<\/p>\n<p>\u0412 Angular \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445<\/p>\n<h4>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u043e\u043c<\/h4>\n<p>\u041e\u0431\u044b\u0447\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431: \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u043e \u0441\u0432\u043e\u0438\u043c\u0438 \u0441\u0442\u0438\u043b\u044f\u043c\u0438 \u0438 \u043b\u043e\u0433\u0438\u043a\u043e\u0439, \u0430 Angular \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0433\u043e \u0432 DOM-\u0434\u0435\u0440\u0435\u0432\u043e, \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 HTML-\u044d\u043b\u0435\u043c\u0435\u043d\u0442.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442:<\/p>\n<pre><code class=\"typescript\">import { Component } from '@angular\/core';  @Component({   selector: 'lib-ui-kit',  <\/code><\/pre>\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-461593","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/461593","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=461593"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/461593\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=461593"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=461593"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=461593"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}