1import{dW as e,bF as n,ap as t,N as a,h as r,aV as o,bW as s,bR as i,ck as l,s as c,aE as d,at as u,aA as m,aM as p,v as g,w as f,av as M,bl as b,bc as y,F as h,I as v,J as w,bK as O,aY as F,bP as S,t as j,u as I,as as R,cB as x}from"./rPzCxgu2.js";import _ from"./Djm02ss4.js";import{_ as C}from"./Vf7itc8G.js";import A from"./BvWp3utU.js";import T from"./BZFqKOVV.js";import P from"./CMqbmjDo.js";import{highlightCode as E,detectSourceLanguage as V}from"./D-GLYPUm.js";import{U as z}from"./B2ngeV_0.js";import{p as D}from"./Bw7o3a0Q.js";/* empty css */import"./DyA0rmCF.js";import"./z1uGv1XI.js";import"./BIVETZJT.js";import"./D1DH0B25.js";import"./DH8wk0CJ.js";import"./Do6aoiPI.js";import"./Brf0lwdd.js";import"./B9HCdCam.js";import"./BP0Qtch8.js";import"./CdFh0n3O.js";import"./CUlxn__V.js";import"./Cigs5uJq.js";import"./D_8At7Qg.js";import"./XSGnpf5l.js";import"./YuzqTGE4.js";import"./CmalZX-0.js";import"./BiVzHQPq.js";import"./BvIBVZyP.js";import"./B6ZI0tfh.js";import"./BCo6x5W8.js";import"./DKpIrpRZ.js";/* empty css *//* empty css */import"./WnJqaMM1.js";import"./DEA_DsvZ.js";const L=e=>Object.freeze({href:`https://gitlab.infotecsglobal.net/techart.infotecs.ru/frontend-cabinet/-/blob/main/${e}`,label:e.split("/").pop(),path:e}),k=Object.freeze([Object.freeze({expected:"ÐÑовеÑÑеÑ, ÑÑо destroy() оÑменÑÐµÑ ÑекÑÑие опеÑаÑии, Ñовно один Ñаз оÑÐ²Ð¾Ð±Ð¾Ð¶Ð´Ð°ÐµÑ Ð²Ñе ÑкземплÑÑÑ Ð¸ не позволÑÐµÑ Ð·Ð°Ð½Ð¾Ð²Ð¾ иниÑиализиÑоваÑÑ ÑниÑÑоженнÑй менеджеÑ.",id:"MMV2-T01",source:L("src/classes/ModalManager/__tests__/ModalManagerV2.test.js"),title:"ÐолноÑÑÑÑ ÑниÑÑожиÑÑ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ"}),Object.freeze({expected:"ÐÑовеÑÑÐµÑ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ðµ глобалÑного менеджеÑа: иÑÑеÑение вÑемени и AbortSignal Ð´Ð¾Ð»Ð¶Ð½Ñ Ð²ÐµÑнÑÑÑ Ð¿ÑедÑказÑемÑе оÑибки и ÑдалиÑÑ Ð¾Ð±ÑабоÑÑики ÑобÑÑий и ÑаймеÑ.",id:"MMV2-T02",source:L("src/classes/ModalManager/__tests__/waitForModalManagerV2.test.js"),title:"ÐÑеÑваÑÑ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ðµ гоÑовноÑÑи"}),Object.freeze({expected:"ÐÑовеÑÑеÑ, ÑÑо неизвеÑÑнÑй ID, некоÑÑекÑное опиÑание окна и ÑкземплÑÑ Ð´ÑÑгого менеджеÑа оÑклонÑÑÑÑÑ Ð±ÐµÐ· Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ ÑекÑÑего ÑоÑÑоÑниÑ.",id:"MMV2-T03",source:L("src/classes/ModalManager/__tests__/ModalManagerV2.test.js"),title:"ÐÑклониÑÑ Ð½ÐµÐºÐ¾ÑÑекÑнÑе вÑ
однÑе даннÑе"}),Object.freeze({expected:"ÐÑовеÑÑÐµÑ Ð¸Ð·Ð¾Ð»ÑÑÐ¸Ñ Ð¾Ñибок в lifecycle hook, подпиÑÑике и оÑиÑÑке. ÐаÑегиÑÑÑиÑованнÑе ÑÑнкÑии оÑиÑÑки Ð´Ð¾Ð»Ð¶Ð½Ñ Ð²ÑполниÑÑÑÑ Ð¾Ð´Ð¸Ð½ Ñаз в обÑаÑном поÑÑдке.",id:"MMV2-T04",source:L("src/classes/ModalManager/__tests__/ModalManagerV2.test.js"),title:"ÐзолиÑоваÑÑ Ð¾Ñибки и вÑполниÑÑ Ð¾ÑиÑÑкÑ"}),Object.freeze({expected:"ÐÑовеÑÑÐµÑ Ð¿Ð°ÑаллелÑнÑе load(), prepare() и open(): Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ð°Ñ ÑабоÑа не должна дÑблиÑоваÑÑÑÑ, а пÑавила Ñ
ÑÐ°Ð½ÐµÐ½Ð¸Ñ Ð·Ð°Ð³ÑÑженного компоненÑа Ð´Ð¾Ð»Ð¶Ð½Ñ Ð´Ð°Ð²Ð°ÑÑ ÑÑабилÑнÑй ÑезÑлÑÑаÑ.",id:"MMV2-T05",source:L("src/classes/ModalManager/__tests__/ModalManagerV2.test.js"),title:"РазÑеÑиÑÑ Ð³Ð¾Ð½ÐºÐ¸ паÑаллелÑнÑÑ
вÑзовов"})]),N=e=>({code:e?.code??null,message:e?.message??String(e),name:e?.name??"Error"}),G=Object.freeze({description:"ÐапÑÑÐºÐ°ÐµÑ Ð´ÐµÐ¹ÑÑвие длиÑелÑноÑÑÑÑ 1,5 ÑекÑндÑ, блокиÑÑÐµÑ ÐµÐ³Ð¾ повÑоÑнÑй запÑÑк и ÑÐ¼ÐµÐµÑ ÐºÐ¾ÑÑекÑно оÑменÑÑÑ ÑабоÑÑ Ð¿Ñи закÑÑÑии окна.",expected:["Ðока дейÑÑвие вÑполнÑеÑÑÑ, поле busyActionId ÑодеÑÐ¶Ð¸Ñ ID кнопки confirm, а кнопка недоÑÑÑпна Ð´Ð»Ñ Ð¿Ð¾Ð²ÑоÑного запÑÑка.","ÐовÑоÑнÑй вÑзов полÑÑÐ°ÐµÑ Ñже вÑполнÑÑÑÑÑÑÑ Ð¾Ð¿ÐµÑаÑÐ¸Ñ (single-flight), а не ÑоздаÑÑ Ð²ÑоÑÑÑ.","ÐакÑÑÑие окна или ÑбÑÐ¾Ñ ÐºÐµÐ¹Ñа оÑменÑÐµÑ AbortSignal, вÑполнÑÐµÑ Ð¾ÑиÑÑÐºÑ Ð¸ игноÑиÑÑÐµÑ Ð·Ð°Ð¿Ð¾Ð·Ð´Ð°Ð²Ñий ÑезÑлÑÑаÑ."],group:"ÐÑинÑ
ÑоннÑе дейÑÑвиÑ",
1id:"MMV2-A01",safety:"read-only",tags:["async","busy","abort"],title:"ÐаблокиÑоваÑÑ Ð¿Ð¾Ð²ÑоÑнÑй запÑÑк дейÑÑвиÑ",useWhen:"ÐÐ»Ñ Ð°ÑинÑ
Ñонной ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð²Ð½ÑÑÑи окна, коÑоÑÑÑ Ð½ÐµÐ»ÑÐ·Ñ Ð·Ð°Ð¿ÑÑкаÑÑ Ð´Ð²Ð°Ð¶Ð´Ñ Ð¸ коÑоÑÑÑ Ð½Ñжно оÑÑановиÑÑ, еÑли полÑзоваÑÐµÐ»Ñ Ð·Ð°ÐºÑÑл окно."}),$=Object.freeze(Object.defineProperty({__proto__:null,recipe:G,run:async({log:e,manager:n,own:t})=>{const a=t(await n.prepare("ModalPrompt",{details:"ÐажмиÑе «ÐапÑÑÑиÑÑ 1,5 Ñ». Ðа вÑÐµÐ¼Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° ÑÑÐ°Ð½ÐµÑ Ð½ÐµÐ´Ð¾ÑÑÑпной, а busyActionId бÑÐ´ÐµÑ Ñавен confirm."}));a.setText("title","MMV2-A01: аÑинÑ
Ñонное дейÑÑвие").setAction({closePolicy:"never",id:"confirm",role:"primary",text:"ÐапÑÑÑиÑÑ 1,5 Ñ"}).setActionHandler("confirm",async({flow:n,instance:t,onCleanup:a,signal:r})=>(e("ÐÑинÑ
Ñонное дейÑÑвие наÑаÑо",t.getState()),!(await new Promise(n=>{const t=setTimeout(e=>n(!0),1500),o=e=>{clearTimeout(t),n(!1)};r.addEventListener("abort",o,{once:!0}),a(n=>{clearTimeout(t),r.removeEventListener("abort",o),e("РеÑÑÑÑÑ Ð°ÑинÑ
Ñонного дейÑÑÐ²Ð¸Ñ Ð¾ÑиÑенÑ")})}))||r.aborted?n.stay({aborted:!0}):(t.setProps({details:"ÐÑинÑ
Ñонное дейÑÑвие завеÑÑено; окно оÑÑалоÑÑ Ð¾ÑкÑÑÑÑм."}),e("ÐÑинÑ
Ñонное дейÑÑвие завеÑÑено",t.getState()),n.stay({completed:!0})))),await n.open(a),e("ModalPrompt гоÑов к аÑинÑ
ÑÐ¾Ð½Ð½Ð¾Ð¼Ñ Ð´ÐµÐ¹ÑÑвиÑ",a.getState())}},Symbol.toStringTag,{value:"Module"})),U=Object.freeze({description:"ÐÑкÑÑÐ²Ð°ÐµÑ ÑÑандаÑÑное окно оÑибки ModalError и добавлÑÐµÑ ÐºÐ½Ð¾Ð¿ÐºÑ Ð¿Ð¾Ð²ÑоÑной попÑÑки, коÑоÑÐ°Ñ Ð½Ðµ закÑÑÐ²Ð°ÐµÑ Ð¾ÐºÐ½Ð¾.",expected:["СÑÑока, поÑ
Ð¾Ð¶Ð°Ñ Ð½Ð° HTML-код, вÑводиÑÑÑ Ð¾Ð±ÑÑнÑм ÑекÑÑом и не иÑполнÑеÑÑÑ Ð±ÑаÑзеÑом.","Ðаждое нажаÑие «ÐовÑоÑиÑÑ» ÑвелиÑÐ¸Ð²Ð°ÐµÑ ÑÑÑÑÑик, пÑинадлежаÑий ÑолÑко ÑÑÐ¾Ð¼Ñ ÑкземплÑÑÑ Ð¾ÐºÐ½Ð°.","РезÑлÑÑÐ°Ñ flow.stay оÑÑавлÑÐµÑ ÑÐ¾Ñ Ð¶Ðµ ÑкземплÑÑ Ð¾ÑкÑÑÑÑм поÑле обÑабоÑÑика."],group:"СÑандаÑÑнÑе окна",id:"MMV2-C01",safety:"read-only",tags:["ModalError","retry","stay"],title:"ÐÑибка Ñ Ð¿Ð¾Ð²ÑоÑной попÑÑкой",useWhen:"ÐÐ»Ñ Ð¸ÑпÑавимой оÑибки инÑеÑÑейÑа или API, поÑле коÑоÑой полÑзоваÑÐµÐ»Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñно повÑоÑиÑÑ Ð¾Ð¿ÐµÑаÑиÑ."}),B=Object.freeze(Object.defineProperty({__proto__:null,recipe:U,run:async({log:e,manager:n,own:t})=>{const a=t(await n.prepare("ModalError",{details:`<script>${["al","ert"].join("")}("не вÑполниÑÑÑ")<\/script>`,messages:["ÐемонÑÑÑаÑÐ¸Ð¾Ð½Ð½Ð°Ñ Ð¾Ñибка. ÐаннÑе на ÑеÑвеÑе не изменÑÑÑÑÑ."]}));a.setText("title","MMV2-C01: оÑибка Ñ Ð¿Ð¾Ð²ÑоÑной попÑÑкой").setStore("retryCount",0).setAction({closePolicy:"never",id:"retry",role:"primary",text:"ÐовÑоÑиÑÑ"}).setActionHandler("retry",({flow:n,instance:t})=>{const a=(t.getStore("retryCount")??0)+1;return t.setStore("retryCount",a).setProps({messages:[`ÐопÑÑка ${a} вÑполнена локалÑно.`]}),e("ÐовÑоÑÐ½Ð°Ñ Ð¿Ð¾Ð¿ÑÑка завеÑÑена; окно оÑÑалоÑÑ Ð¾ÑкÑÑÑÑм",{retryCount:a}),n.stay({retryCount:a})}
1),await n.open(a),e("ModalError оÑкÑÑÑ",a.getState())}},Symbol.toStringTag,{value:"Module"})),W=Object.freeze({description:"ÐÑкÑÑÐ²Ð°ÐµÑ ÑÑандаÑÑное окно ModalSuccess, ÑообÑÐ°ÐµÑ Ð¾Ð± ÑÑпеÑном завеÑÑении опеÑаÑии и пÑÐµÐ´Ð»Ð°Ð³Ð°ÐµÑ Ð·Ð°ÐºÑÑÑÑ Ñведомление.",expected:["ÐоÑоÑÐºÐ°Ñ ÑоÑма open пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ title и message; пеÑеданнÑй message заменÑÐµÑ default-ÑекÑÑ Ð¾ÐºÐ½Ð°.","ÐÑÑÑой message ÑкÑÑÐ²Ð°ÐµÑ default-ÑекÑÑ, а messages вÑÐ²Ð¾Ð´Ð¸Ñ Ð¾ÑделÑнÑе пÑнкÑÑ ÑпиÑка без default-ÑекÑÑа.","Ðнопка «ÐакÑÑÑÑ» иÑполÑзÑÐµÑ Ð²ÑÑÑоенное закÑÑÑие и не ÑÑебÑÐµÑ Ð¾ÑделÑного обÑабоÑÑика.","Promise instance.closed ÑообÑÐ°ÐµÑ Ð¿ÑиÑÐ¸Ð½Ñ Ð·Ð°ÐºÑÑÑÐ¸Ñ (reason) и пеÑеданнÑй ÑезÑлÑÑÐ°Ñ (result)."],group:"СÑандаÑÑнÑе окна",id:"MMV2-C02",safety:"read-only",tags:["ModalSuccess","close","result"],title:"СообÑиÑÑ Ð¾Ð± ÑÑпеÑном завеÑÑении",useWhen:"ÐоÑле оконÑаÑелÑно завеÑÑÑнной опеÑаÑии, когда полÑзоваÑÐµÐ»Ñ Ð½Ñжно показаÑÑ ÑезÑлÑÑÐ°Ñ Ð¸ вÑвеÑÑи его из ÑекÑÑего Ñага."}),q=Object.freeze(Object.defineProperty({__proto__:null,recipe:W,run:async({log:e,manager:n,own:t})=>{e("ModalSuccess оÑкÑÑÑ Ñо вÑÑÑоеннÑм дейÑÑвием закÑÑÑиÑ",t(await n.open("ModalSuccess",{message:"ÐпеÑаÑÐ¸Ñ Ð·Ð°Ð²ÐµÑÑена в демонÑÑÑаÑионном Ñежиме.",title:"MMV2-C02: опеÑаÑÐ¸Ñ Ð·Ð°Ð²ÐµÑÑена"})).getState())}},Symbol.toStringTag,{value:"Module"})),H=Object.freeze({description:"ÐÑкÑÑÐ²Ð°ÐµÑ Ð¾ÐºÐ½Ð¾ подÑвеÑÐ¶Ð´ÐµÐ½Ð¸Ñ ModalPrompt и оÑделÑÐµÑ Ñвное ÑоглаÑие Ð¾Ñ Ð»Ñбого ÑпоÑоба оÑÐ¼ÐµÐ½Ñ Ð¸Ð»Ð¸ закÑÑÑиÑ.",expected:["ТолÑко кнопка подÑвеÑÐ¶Ð´ÐµÐ½Ð¸Ñ ÑвелиÑÐ¸Ð²Ð°ÐµÑ ÑÑÑÑÑик вÑполненнÑÑ
команд businessActionCount.","ÐÑмена, Escape, кнопка закÑÑÑÐ¸Ñ Ð¸ клик по ÑÐ¾Ð½Ñ Ð·Ð°ÐºÑÑваÑÑ Ð¾ÐºÐ½Ð¾ без вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ.","ÐовÑоÑное подÑвеÑждение во вÑÐµÐ¼Ñ Ñже запÑÑенного дейÑÑÐ²Ð¸Ñ Ð½Ðµ ÑоздаÑÑ Ð²ÑоÑÑÑ Ð¾Ð¿ÐµÑаÑиÑ."],group:"СÑандаÑÑнÑе окна",id:"MMV2-C03",safety:"read-only",tags:["ModalPrompt","confirm","dismiss"],title:"ÐапÑоÑиÑÑ Ð¿Ð¾Ð´ÑвеÑждение дейÑÑвиÑ",useWhen:"ÐеÑед командой, коÑоÑÑÑ ÑазÑеÑено вÑполнÑÑÑ ÑолÑко поÑле Ñвного ÑоглаÑÐ¸Ñ Ð¿Ð¾Ð»ÑзоваÑелÑ, но не пÑи закÑÑÑии окна."}),X=Object.freeze(Object.defineProperty({__proto__:null,recipe:H,run:async({log:e,manager:n,own:t})=>{const a=t(await n.prepare("ModalPrompt",{details:"ÐодÑвеÑдиÑе локалÑнÑÑ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑаÑионнÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ."}));a.setText("title","MMV2-C03: подÑвеÑдиÑе дейÑÑвие").setPresentation({dismiss:{backdrop:!0}}).setStore("businessActionCount",0).setActionHandler("confirm",({flow:n,instance:t})=>{const a=(t.getStore("businessActionCount")??0)+1;return t.setStore("businessActionCount",a),e("Ðоманда вÑполнена поÑле Ñвного подÑвеÑждениÑ",{businessActionCount:a}),n.close({businessActionCount:a,confirmed:!0})}),await n.open(a),e("ModalPrompt Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ ÑеÑениÑ",a.getState())}},Symbol.toStringTag,{value:"Module"})),J=Object.freeze({description:"СоздаÑÑ Ð½ÐµÐ±Ð¾Ð»ÑÑой ÑекÑÑовÑй Ñайл пÑÑмо в бÑаÑзеÑе и показÑÐ²Ð°ÐµÑ ÑÑандаÑÑное окно загÑÑзки ModalDownload.",expected:["Файл не загÑÑжаеÑÑÑ Ð°Ð²ÑомаÑиÑеÑки: полÑзоваÑÐµÐ»Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ Ñвно нажаÑÑ ÐºÐ½Ð¾Ð¿ÐºÑ Ð·Ð°Ð³ÑÑзки.","Ðкно полÑÑÐ°ÐµÑ Ð²ÑеменнÑй адÑÐµÑ blob:, ÑозданнÑй бÑаÑзеÑом, поÑÑÐ¾Ð¼Ñ Ð·Ð°Ð¿ÑÐ¾Ñ Ðº API не вÑполнÑеÑÑÑ.","ÐÑи закÑÑÑии окна или ÑбÑоÑе кейÑа вÑеменнÑй Object URL оÑвобождаеÑÑÑ."],group:"СÑандаÑÑнÑе окна",id:"MMV2-C04",safety:"local-side-effect",tags:["ModalDownload","Blob","cleanup"],title:"ÐоказаÑÑ Ð·Ð°Ð³ÑÑÐ·ÐºÑ Ð»Ð¾ÐºÐ°Ð»Ñного Ñайла",useWhen:"ÐÐ»Ñ Ð¿ÑовеÑки инÑеÑÑейÑа загÑÑзки без обÑаÑÐµÐ½Ð¸Ñ Ðº API и без Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ
на ÑеÑвеÑе."}),K=Object.freeze(Object.defineProperty({__proto__:null,recipe:J,run:async({createLocalObjectUrl:e,globalTarget:n,log:t,manager:a,own:r})=>{const o=new n.Blob(["ModalManagerV2 local recipe\n"],{type:"text/plain;charset=utf-8"}),{revoke:s,url:i}=e(o),l=r(await a.prepare("ModalDownload",{autoClose:!1,autoStart:!1,countdown:0,filename:"modal-manager-v2-recipe.txt",url:i}));l.setText("title","MMV2-C04: локалÑнÑй Ñайл").onDispose(s),await a.open(l),t("ModalDownload оÑкÑÑÑ Ñ Ð»Ð¾ÐºÐ°Ð»ÑнÑм Blob URL",{filename:"modal-manager-v2-recipe.txt",protocol:new n.URL(i).protocol})}},Symbol.toStringTag,{value:"Module"})),Y="Catalog/ProductFilters",Z=Object.freeze([Object.freeze({label:"ФабÑика ÑоÑÐ¼Ñ Ð² lazy-каÑалоге",source:"// dependencies: form-generator\nimport { Form, Param
1sMaker } from '@plugins/vue3-form-generator/src/';\n\n// components\nimport UIChipAccordion from '@ui/ChipAccordion/form-generator.js';\nimport UISearchField from '@ui/SearchField/form-generator.js';\n\n\nlet sequence = 0;\n\nconst demoGroups = [\n {\n name: 'productLines',\n label: 'Ðинейки пÑодÑкÑов',\n items: [\n { id: 'network', text: 'ÐаÑиÑа каналов ÑвÑзи' },\n { id: 'endpoint', text: 'ÐаÑиÑа конеÑнÑÑ
ÑÑÑÑойÑÑв' },\n { id: 'industry', text: 'ÐаÑиÑа ÑиÑÑем авÑомаÑизаÑии' },\n { id: 'communications', text: 'ÐаÑиÑÑннÑе коммÑникаÑии' },\n { id: 'analytics', text: 'ÐналиÑика безопаÑноÑÑи' },\n ],\n },\n {\n name: 'productTypes',\n label: 'Ð¢Ð¸Ð¿Ñ Ð¿ÑодÑкÑов',\n items: [\n { id: 'ngfw', text: 'NGFW' },\n { id: 'management', text: 'СиÑÑÐµÐ¼Ñ ÑпÑавлениÑ' },\n { id: 'gateway', text: 'ШлÑÐ·Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑÑи' },\n { id: 'clients', text: 'ÐлиенÑÑкие пÑиложениÑ' },\n { id: 'screens', text: 'ÐежÑеÑевÑе ÑкÑанÑ' },\n ],\n },\n {\n name: 'platforms',\n label: 'ÐпеÑаÑионнÑе ÑиÑÑемÑ',\n items: [\n { id: 'linux', text: 'Linux' },\n { id: 'windows', text: 'Windows' },\n { id: 'android', text: 'Android' },\n { id: 'macos', text: 'MacOS' },\n { id: 'ios', text: 'iOS' },\n ],\n },\n];\n\nexport function createProductFiltersRuntime(input = {}) {\n sequence += 1;\n const groups = input.groups ?? demoGroups;\n const form = new Form({\n baseId: 'form-manager',\n key: `product-filters-${sequence}`,\n prefix: 'form-manager-filter-',\n })\n .setParams({\n id: input.formId ?? `form-manager-product-filters-${sequence}`,\n buttons: [ParamsMaker.genButton('send', 'ÐоказаÑÑ')],\n hasFieldset: false,\n hasGroups: false,\n hasSteps: false,\n })\n .addField(UISearchField, {\n name: 'query',\n label: 'ÐоиÑк',\n value: input.query ?? '',\n params: {\n options: { isLabelHidden: true },\n texts: { placeholder: 'Ðазвание пÑодÑкÑаâ¦' },\n },\n });\n\n for (const group of groups) {\n form.addField(UIChipAccordion, {\n name: group.name,\n label: group.label,\n value: [...(input.selected?.[group.name] ?? [])],\n params: {\n items: group.items.map(item => ({ ...item })),\n visibleCount: group.visibleCount ?? 3,\n sort: { by: 'original', direction: 'asc' },\n selectedFirst: false,\n showSearch: false,\n showReset: false,\n },\n });\n }\n\n form.setup().setReady();\n const { form: dataForm, functions } = form;\n return { dataForm, functions, title: 'ФилÑÑÑÑ' };\n}\n\nexport default createProductFiltersRuntime;\n"}),Object.freeze({label:"РазмеÑка ÑÑиггеÑа во frontend Blade",source:"<div data-product-filter-trigger>\n @php\n echo \\Infotecs\\UiRenderer\\UiRenderer::render('/common/chip/chip', [\n 'id' => 'product-filters-trigger',\n 'name' => 'ФилÑÑÑÑ',\n ], false);\n @endphp\n</div>"}),Object.freeze({label:"ÐодклÑÑение из оÑделÑного frontend bundle",source:"const waitForServices = (timeout = 10_000) => new Promise((resolve, reject) => {\n let settled = false;\n let resolving = false;\n const cleanup = _ => {\n clearTimeout(timer);\n document.removeEventListener('modal-manager-v2:ready', onReady);\n };\n const fail = error => {\n if (settled) return;\n settled = true;\n cleanup();\n reject(error);\n };\n const check = _ => {\n const { ModalManagerV2, FormManager } = globalThis.infotecs ?? {};\n if (!ModalManagerV2 || !FormManager || settled || resolving) return;\n resolving = true;\n Promise.all([ModalManagerV2.whenReady(), FormManager.whenReady()])\n .then(_ => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve({ ModalManagerV2, FormManager });\n })\n .catch(fail);\n };\n function onReady() { check(); }\n\n const timer = setTimeout(\n _ => fail(new Error('СеÑвиÑÑ frontend-cabinet не гоÑовÑ')),\n timeout,\n );\n document.addEventListener('modal-manager-v2:ready', onReady);\n check();\n});\n\nconst appliedFilters = new WeakMap();\n\ndocument.addEventListener('product-filters:apply', event => {\n const trigger = event.target.closest?.('[data-product-filter-trigger]');\n if (!trigger) return;\n\n const fields = Array.isArray(event.detail?.fields) ? event.detail.fields : [];
1\n const query = String(fields.find(field => field.name === 'query')?.model ?? '');\n const selected = Object.fromEntries(fields\n .filter(field => field.name !== 'query' && Array.isArray(field.model))\n .map(field => [field.name, [...field.model]]));\n const count = (query.trim() ? 1 : 0)\n + Object.values(selected).reduce((total, values) => total + values.length, 0);\n\n appliedFilters.set(trigger, { query, selected });\n const chip = trigger.querySelector('.b-chip-wrapper')?.__interface;\n chip?.setParam('count', count || null);\n chip?.setParam('active', count > 0);\n});\n\nlet opening = false;\ndocument.addEventListener('infotecs-ui-click', async event => {\n const trigger = event.target.closest?.('[data-product-filter-trigger]');\n if (!trigger || opening) return;\n opening = true;\n try {\n const { ModalManagerV2, FormManager } = await waitForServices();\n const instance = await FormManager.open('Catalog/ProductFilters', {\n ...appliedFilters.get(trigger),\n groups: [\n {\n name: 'productLines',\n label: 'Ðинейки пÑодÑкÑов',\n items: [{ id: 'network', text: 'ÐаÑиÑа каналов ÑвÑзи' }],\n },\n {\n name: 'platforms',\n label: 'ÐпеÑаÑионнÑе ÑиÑÑемÑ',\n items: [{ id: 'linux', text: 'Linux' }],\n },\n ],\n }, {\n mount: ModalManagerV2,\n presentation: { preset: 'sheet', side: 'right' },\n });\n const { result } = await instance.closed;\n if (result) trigger.dispatchEvent(new CustomEvent('product-filters:apply', {\n bubbles: true,\n detail: result,\n }));\n } catch (error) {\n trigger.dispatchEvent(new CustomEvent('product-filters:error', {\n bubbles: true,\n detail: error,\n }));\n } finally {\n opening = false;\n }\n});\n"})]),Q=e=>{const n=Array.isArray(e?.fields)?e.fields:[],t=String(n.find(e=>"query"===e.name)?.model??""),a=Object.fromEntries(n.filter(e=>"query"!==e.name&&Array.isArray(e.model)).map(e=>[e.name,[...e.model]])),r=(t.trim()?1:0)+Object.values(a).reduce((e,n)=>e+n.length,0);return{query:t,selected:a,count:r}},ee=Object.freeze({description:"UIChip оÑкÑÑÐ²Ð°ÐµÑ Ð±Ð¾ÐºÐ¾Ð²ÑÑ ÑÑоÑÐºÑ Ñ FormGenerator-ÑилÑÑÑом: одно поле обÑего поиÑка и неÑколÑко гÑÑпп ChipAccordion без внÑÑÑеннего поиÑка. ФоÑма пÑÐ¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ lazy-каÑÐ°Ð»Ð¾Ð³Ñ frontend-cabinet, а поÑÑебиÑÐµÐ»Ñ Ð¿ÐµÑедаÑÑ Ð³ÑÑÐ¿Ð¿Ñ Ð¸ полÑÑÐ°ÐµÑ ÑезÑлÑÑÐ°Ñ ÑеÑез FormManager.",expected:["ÐажаÑие на Ñип «ФилÑÑÑÑ» оÑкÑÑÐ²Ð°ÐµÑ ÑпÑава ÑÑоÑÐºÑ Ñ Ð¿Ð¾Ð¸Ñком и ÑÑÐµÐ¼Ñ Ð³ÑÑппами ваÑианÑов.","Ркаждой гÑÑппе Ð²Ð¸Ð´Ð½Ñ Ð¿ÐµÑвÑе ÑÑи ваÑианÑа, оÑÑалÑнÑе ÑаÑкÑÑваÑÑÑÑ; оÑделÑного поиÑка внÑÑÑи ChipAccordion неÑ.","«ÐоказаÑÑ» закÑÑÐ²Ð°ÐµÑ ÑоÑмÑ: ÑиÑÑа на Ñипе Ñавна ÑиÑÐ»Ñ Ð²ÑбÑаннÑÑ
ваÑианÑов плÑÑ Ð¾Ð´Ð¸Ð½ за непÑÑÑой поиÑковÑй запÑоÑ.","ÐовÑоÑное оÑкÑÑÑие ÑоздаÑÑ Ð½Ð¾Ð²Ñй FormInstance Ñ ÑоÑ
ÑанÑннÑми кÑиÑеÑиÑми; ÑбÑÐ¾Ñ ÐºÐµÐ¹Ñа закÑÑÐ²Ð°ÐµÑ ÑÑоÑÐºÑ Ð¸ оÑиÑÐ°ÐµÑ Ñип."],group:"СÑандаÑÑнÑе окна",id:"MMV2-C05",safety:"read-only",tags:["UIChip","ChipAccordion","FormManager","sheet"],title:"ФилÑÑÑ Ð¿ÑодÑкÑов в ÑÑоÑке",trigger:"chip",useWhen:"Ðогда оÑделÑнÑй frontend-ÑкÑÐ¸Ð¿Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ оÑкÑÑÑÑ ÑоÑмÑ-ÑилÑÑÑ Ð¿Ð¾ ÑÑабилÑÐ½Ð¾Ð¼Ñ ID поÑле гоÑовноÑÑи ÑеÑвиÑов, не импоÑÑиÑÑÑ Vue и адапÑеÑÑ FormGenerator.",warnings:["ÐемонÑÑÑаÑионнÑе ваÑианÑÑ Ð½Ðµ ÑвлÑÑÑÑÑ Ð°ÐºÑÑалÑнÑм каÑалогом пÑодÑкÑов; ÑеалÑнÑе гÑÑÐ¿Ð¿Ñ Ð¸ обÑабоÑÐºÑ ÑезÑлÑÑаÑа задаÑÑ Ð²ÑзÑваÑÑий код.","ÐоиÑк â оÑделÑнÑй кÑиÑеÑий ÑоÑмÑ, а не ÑилÑÑÑаÑÐ¸Ñ Ñипов внÑÑÑи гÑÑпп.","РпÑимеÑе Ð´Ð»Ñ frontend аÑÑибÑÑ data-product-filter-trigger ÑÑавиÑÑÑ Ð½Ð° обÑÑÑÐºÑ ÑмонÑиÑованного UIChip; ÑобÑÑие infotecs-ui-click вÑплÑÐ²Ð°ÐµÑ Ð¾Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸.","СкÑÐ¸Ð¿Ñ frontend обÑабаÑÑÐ²Ð°ÐµÑ ÑобÑÑÐ¸Ñ product-filters:apply и product-filters:error на обÑÑÑке Ñипа; пÑÐ¸Ð¼ÐµÑ Ð½Ðµ менÑÐµÑ ÑпиÑок пÑодÑкÑов.","ФоÑÐ¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ заÑегиÑÑÑиÑоваÑÑ Ð²Ð¾ вÑÐµÐ¼Ñ ÑабоÑÑ ÑÑÑаниÑÑ ÑеÑез setForm(), но ÑÑо менÑÐµÑ Ð¾Ð±Ñий каÑалог ÑоÑм. ÐдеÑÑ Ñаблон подгоÑовлен в frontend-cabinet, а ваÑианÑÑ Ð¿ÐµÑедаÑÑÑÑ Ð¿Ñи оÑкÑÑÑии из frontend."]}),ne=Object.freeze(Object.defineProperty({__proto__:null,default:ee,readProductFilters:Q,recipe:ee,run:async({appliedFilters:n={},globalTarget:t,log:a,namespaceKey:r,onFiltersApplied:o=e=>null,own:s})=>{const i=t[r],l=i?.ModalManagerV2,c=i?.FormManager;if(!l||!c)throw new Error("ModalManagerV2 and FormManager are required");await Promise.all([l.whenReady(),c.whenReady()]);const d=s(await c.open(Y,{query:n.query??"",selected:n.selected??{}},{mount:l,onSubmit:n=>{const t=n?.sendData?.data??null,r=Q(t);return o(r),a("ÐÑиÑеÑии ÑилÑÑÑа пеÑÐµÐ´Ð°Ð½Ñ Ð¿Ð¾ÑÑебиÑелÑ",{filters:r,result:t}),e.close(t)},presentation:{preset:"sheet",side:"right"}}));a("ФилÑÑÑ Ð¾ÑкÑÑÑ Ð¿Ð¾ ID гоÑовой ÑоÑмÑ",{formId:Y,instanceId:d.instanceId,modalId:d.mountResult.id})},supportingSources:Z},Symbol.toStringTag,{value:"Module"})),te=Object.freeze({description:"ÐоказÑÐ²Ð°ÐµÑ ÑазниÑÑ Ð¼ÐµÐ¶Ð´Ñ Ð¿Ð¾Ð²ÑоÑнÑм вÑзовом open() Ð´Ð»Ñ ÑÑÑеÑÑвÑÑÑего ÑкземплÑÑа и Ñозданием нового окна поÑле закÑÑÑиÑ.",expected:["ÐовÑоÑнÑй open() до закÑÑÑÐ¸Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÑ ÑÐ¾Ñ Ð¶Ðµ обÑÐµÐºÑ Ð¸ не ÑоздаÑÑ Ð´ÑÐ±Ð»Ð¸ÐºÐ°Ñ Ð¾ÐºÐ½Ð°.","Ðнопка «ÐакÑÑÑÑ Ð¸ оÑкÑÑÑÑ Ð½Ð¾Ð²Ñй» оконÑаÑелÑно завеÑÑÐ°ÐµÑ Ð¿ÐµÑвÑй ÑкземплÑÑ.","СледÑÑÑий prepare() ÑоздаÑÑ Ð½Ð¾Ð²Ñй instanceId Ð´Ð»Ñ Ñого же Ñипа модалÑного окна."],group:"ÐизненнÑй Ñикл",id:"MMV2-L01",safety:"read-only",tags:["repeated-open","closed","identity"],title:"ÐовÑоÑно оÑкÑÑÑÑ Ð¾ÐºÐ½Ð¾ поÑле закÑÑÑиÑ",useWhen:"ЧÑÐ¾Ð±Ñ Ð½Ðµ ÑоздаваÑÑ Ð´ÑбликаÑÑ Ñже оÑкÑÑÑого окна и пÑавилÑно наÑинаÑÑ Ð½Ð¾Ð²Ñй жизненнÑй Ñикл поÑле его закÑÑÑиÑ."}),ae=Object.freeze(Object.defineProperty({__proto__:null,recipe:te,run:async({log:e,manager:n,own:t,signal:a})=>{const r=t(await n.prepare("ModalSuccess",{messages:["ÐеÑвÑй ÑкземплÑÑ."]}));r.setText("title","MMV2-L01: пеÑвÑй ÑкземплÑÑ").setAction({closePolicy:"never",id:"reopen",role:"primary",text:"ÐакÑÑÑÑ Ð¸ оÑкÑÑÑÑ Ð½Ð¾Ð²Ñй"}).setActionHandler("reopen",({flow:e})=>e.close({reopen:!0}));const o=await n.open(r),s=await n.open(r);e("ÐовÑоÑнÑй open() веÑнÑл ÑÑÑеÑÑвÑÑÑий ÑкземплÑÑ",{identity:s===o,instanceId:r.instanceId}),r.closed.then(async({result:o})=>{if(!o?.reopen||a.aborted)return;const s=t(await n.prepare("ModalSuccess",{messages:["ÐÑо новÑй ÑкземплÑÑ, ÑозданнÑй поÑле полного закÑÑÑÐ¸Ñ Ð¿ÑедÑдÑÑего."]}));s.setText("title","MMV2-L01: новÑй ÑкземплÑÑ").setAction({id:"close",role:"primary",text:"ÐакÑÑÑÑ"}),await n.open(s),e("ÐоÑле закÑÑÑÐ¸Ñ Ñоздан новÑй ÑкземплÑÑ",{changed:s.instanceId!==r.instanceId,first:r.instanceId,fresh:s.instanceId})}).catch(n=>e("Ðе ÑдалоÑÑ Ð¾ÑкÑÑÑÑ Ð½Ð¾Ð²Ñй ÑкземплÑÑ",{code:n?.code??null,message:n?.message??String(n)},"error"))}},Symbol.toStringTag,{value:"Module"})),re=Object.freeze({description:"ÐÑкÑÑÐ²Ð°ÐµÑ Ð¾ÐºÐ½Ð¾ подÑвеÑждениÑ, заÑем показÑÐ²Ð°ÐµÑ Ð¿Ð¾Ð²ÐµÑÑ
него окно оÑибки и ÑоÑ
ÑанÑÐµÑ Ð½Ð¸Ð¶Ð½Ð¸Ð¹ ÑкземплÑÑ.",expected:["Ðижнее окно ModalPrompt полÑÑÐ°ÐµÑ ÑÑаÑÑÑ covered â оно пеÑекÑÑÑо, но оÑÑаÑÑÑÑ ÑмонÑиÑованнÑм.","ÐоÑле закÑÑÑÐ¸Ñ Ð²ÐµÑÑ
него ModalError нижнее окно Ñнова полÑÑÐ°ÐµÑ ÑÑаÑÑÑ open и ÑÑановиÑÑÑ Ð´Ð¾ÑÑÑпнÑм.","СÑек показа и activeModalId вÑегда Ñказ
1ÑваÑÑ Ð½Ð° ÑакÑиÑеÑкий поÑÑдок окон."],group:"ÐизненнÑй Ñикл",id:"MMV2-L02",safety:"read-only",tags:["stack","covered","reveal"],title:"ÐÑкÑÑÑÑ Ð¾ÐºÐ½Ð¾ повеÑÑ
дÑÑгого",useWhen:"ÐÐ»Ñ Ð¿Ð¾ÑледоваÑелÑноÑÑи завиÑимÑÑ
окон, где нижнее окно должно ÑоÑ
ÑаниÑÑ Ð²Ð²ÐµÐ´ÑннÑе даннÑе, пока полÑзоваÑÐµÐ»Ñ ÑабоÑÐ°ÐµÑ Ñ Ð²ÐµÑÑ
ним."}),oe=Object.freeze(Object.defineProperty({__proto__:null,recipe:re,run:async({log:e,manager:n,own:t})=>{const a=t(await n.prepare("ModalPrompt",{details:"ÐакÑойÑе веÑÑ
нÑÑ Ð¾ÑибкÑ, ÑÑÐ¾Ð±Ñ Ð²ÐµÑнÑÑÑÑÑ ÑÑда."}));a.setText("title","MMV2-L02: нижнее окно подÑвеÑждениÑ"),await n.open(a);const r=t(await n.prepare("ModalError",{messages:["ÐÑо веÑÑ
нее окно в ÑÑеке показа."]}));r.setText("title","MMV2-L02: веÑÑ
нÑÑ Ð¾Ñибка"),await n.open(r),e("Ðва окна оÑкÑÑÑÑ ÑлоÑми",{error:r.getState(),manager:n.getState(),prompt:a.getState()})}},Symbol.toStringTag,{value:"Module"})),se=Object.freeze({description:"ÐоÑле подÑвеÑÐ¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°Ð¼ÐµÐ½ÑÐµÑ ÑекÑÑее окно ModalPrompt новÑм окном ModalSuccess без пÑомежÑÑоÑного пÑÑÑого ÑоÑÑоÑниÑ.",expected:["СнаÑала оÑкÑÑваеÑÑÑ Ñелевое окно, заÑем иÑÑ
одное закÑÑваеÑÑÑ Ñ Ð¿ÑиÑиной replaced.","ÐоÑле пеÑеÑ
ода в ÑÑеке показа оÑÑаÑÑÑÑ ÑолÑко ModalSuccess.","ÐаÑалог ÑегиÑÑÑиÑÑÐµÑ Ð½Ð¾Ð²Ð¾Ðµ окно как пÑинадлежаÑее кейÑÑ Ð¸ безопаÑно закÑÑÐ²Ð°ÐµÑ ÐµÐ³Ð¾ пÑи ÑбÑоÑе."],group:"ÐизненнÑй Ñикл",id:"MMV2-L03",safety:"read-only",tags:["replace","flow.open","ownership"],title:"ÐамениÑÑ Ð¾Ð´Ð½Ð¾ окно дÑÑгим",useWhen:"Ðогда ÑледÑÑÑий Ñаг пÑоÑеÑÑа должен полноÑÑÑÑ Ð·Ð°Ð¼ÐµÐ½Ð¸ÑÑ ÑекÑÑее окно, напÑÐ¸Ð¼ÐµÑ Ð¿Ð¾Ð´ÑвеÑждение â ÑообÑением об ÑÑпеÑ
е."}),ie=Object.freeze(Object.defineProperty({__proto__:null,recipe:se,run:async({log:e,manager:n,own:t,signal:a})=>{const r=t(await n.prepare("ModalPrompt",{details:"ÐажмиÑе подÑвеÑждение: ÑÑо окно бÑÐ´ÐµÑ Ð·Ð°Ð¼ÐµÐ½ÐµÐ½Ð¾ ÑообÑением об ÑÑпеÑ
е."}));r.setText("title","MMV2-L03: иÑÑ
одное окно подÑвеÑждениÑ").setActionHandler("confirm",({flow:e})=>e.open("ModalSuccess",{messages:["Ðкно подÑвеÑÐ¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°Ð¼ÐµÐ½ÐµÐ½Ð¾ без пÑомежÑÑоÑного пÑÑÑого ÑÑека."]},{transition:"replace"})),r.closed.then(r=>{if("replaced"!==r.reason||a.aborted)return;const o=n.getInstance("ModalSuccess");o&&t(o),e("Ðамена одного окна дÑÑгим завеÑÑена",{closed:r,manager:n.getState(),targetInstanceId:o?.instanceId??null})}),await n.open(r),e("Ðкно подÑвеÑÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð´Ð»Ñ Ð¿ÐµÑеÑ
ода",r.getState())}},Symbol.toStringTag,{value:"Module"})),le=Object.freeze({description:"ÐÑкÑÑÐ²Ð°ÐµÑ ModalSuccess и ÑеÑез 3 ÑекÑÐ½Ð´Ñ Ð²ÑзÑÐ²Ð°ÐµÑ instance.close(). Раннее закÑÑÑие или ÑбÑÐ¾Ñ ÐºÐµÐ¹Ñа оÑменÑÐµÑ ÑаймеÑ.",expected:["Ðкно закÑÑваеÑÑÑ Ð°Ð²ÑомаÑиÑеÑки ÑеÑез 3 ÑекÑÐ½Ð´Ñ Ð¿Ð¾Ñле показа.","РжÑÑнале ÑезÑлÑÑÐ°Ñ Ð·Ð°ÐºÑÑÑÐ¸Ñ ÑодеÑÐ¶Ð¸Ñ result.timedOut: true; reason оÑÑаÑÑÑÑ programmatic.","ÐÑи закÑÑÑии кнопкой или кÑеÑÑиком ÑанÑÑе ÑÑока ÑÐ°Ð¹Ð¼ÐµÑ Ð¾ÑменÑеÑÑÑ.","ÐовÑоÑнÑй запÑÑк ÑоздаÑÑ Ð½Ð¾Ð²Ñй ÑаймеÑ. СбÑÐ¾Ñ ÐºÐµÐ¹Ñа оÑиÑÐ°ÐµÑ ÐµÐ³Ð¾."],group:"ÐизненнÑй Ñикл",id:"MMV2-L04",safety:"read-only",tags:["timeout","setTimeout","close","onDispose"],title:"ÐакÑÑÑÑ Ð¾ÐºÐ½Ð¾ по ÑаймеÑÑ",useWhen:"ÐÐ»Ñ ÐºÑаÑкого ÑообÑениÑ, коÑоÑое должно иÑÑезнÑÑÑ Ð°Ð²ÑомаÑиÑеÑки ÑеÑез заданное вÑемÑ.",warnings:["Ð¢Ð°Ð¹Ð¼ÐµÑ Ð²ÑзÑÐ²Ð°ÐµÑ instance.close(), а не flow.close(): flow нÑжно веÑнÑÑÑ Ð¸Ð· обÑабоÑÑика дейÑÑвиÑ.","ÐакÑÑÑие пÑоÑ
Ð¾Ð´Ð¸Ñ Ð¾Ð±ÑÑнÑй beforeClose. ÐÑли обÑабоÑÑик запÑеÑÐ¸Ñ Ð·Ð°ÐºÑÑÑие, повÑоÑной попÑÑки по ÑаймеÑÑ Ð½Ðµ бÑдеÑ."]}),ce=Object.freeze(Object.defineProperty({__proto__:null,recipe:le,run:async({log:e,manager:n,own:t,registerCleanup:a,signal:r})=>{const o=t(await n.prepare("ModalSuccess",{message:"Ðкно закÑоеÑÑÑ ÑеÑез 3 ÑекÑндÑ. Ðожно закÑÑÑÑ ÐµÐ³Ð¾ ÑанÑÑе кнопкой или кÑеÑÑиком.",title:"MMV2-L04: Ð
1·Ð°ÐºÑÑÑие по ÑаймеÑÑ"}));let s;const i=e=>clearTimeout(s),l=a(i);o.onDispose(e=>{i(),l()}),o.closed.then(n=>{r.aborted||e(n.result?.timedOut?"Ðкно закÑÑÑо по ÑаймеÑÑ":"Ðкно закÑÑÑо ÑанÑÑе ÑÑока; ÑÐ°Ð¹Ð¼ÐµÑ Ð¾ÑменÑн",n)}),await n.open(o),r.aborted||["closing","closed"].includes(o.status)||(s=setTimeout(n=>{o.close({timedOut:!0}).then(n=>{n||r.aborted||e("ÐакÑÑÑие по ÑаймеÑÑ Ð¾Ñменено")}).catch(n=>{r.aborted||e("ÐÑибка закÑÑÑÐ¸Ñ Ð¿Ð¾ ÑаймеÑÑ",{message:n.message})})},3e3),e("Ð¢Ð°Ð¹Ð¼ÐµÑ Ð·Ð°Ð¿ÑÑен: 3 ÑекÑндÑ",{instanceId:o.instanceId}))}},Symbol.toStringTag,{value:"Module"})),de=Object.freeze({description:"ÐодпиÑÑваеÑÑÑ Ð½Ð° Ñнимки ÑоÑÑоÑÐ½Ð¸Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑа и на пÑблиÑнÑе ÑобÑÑÐ¸Ñ ÑÑÑаниÑÑ, ÑÑÐ¾Ð±Ñ Ð¿Ð¾ÐºÐ°Ð·Ð°ÑÑ Ð¾Ð±Ð° ÑпоÑоба наблÑдениÑ.",expected:["ÐодпиÑÑик ÑÑÐ°Ð·Ñ Ð¿Ð¾Ð»ÑÑÐ°ÐµÑ ÑекÑÑий Ñнимок и заÑем каждÑй Ñнимок Ñ Ð½Ð¾Ð²Ð¾Ð¹ revision.","DOM CustomEvent имеÑÑ Ð¿ÑеÑÐ¸ÐºÑ modal-manager-v2 и ÑодеÑÐ¶Ð°Ñ ÑеÑиализÑемÑе даннÑе в поле detail.","СбÑÐ¾Ñ ÐºÐµÐ¹Ñа оÑпиÑÑÐ²Ð°ÐµÑ ÑÑнкÑиÑ-наблÑдаÑÐµÐ»Ñ Ð¸ ÑдалÑÐµÑ Ð²Ñе DOM-обÑабоÑÑики."],group:"СоÑÑоÑние и ÑобÑÑиÑ",id:"MMV2-O01",safety:"read-only",tags:["subscribe","events","revision"],title:"ÐаблÑдаÑÑ ÑоÑÑоÑние и ÑобÑÑиÑ",useWhen:"ÐÐ»Ñ Ð´Ð¸Ð°Ð³Ð½Ð¾ÑÑики жизненного Ñикла окон или подклÑÑÐµÐ½Ð¸Ñ Ð²Ð½ÐµÑнего наблÑдаÑелÑ, коÑоÑÑй ÑиÑÐ°ÐµÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ, но не ÑпÑавлÑÐµÑ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑом."}),ue=Object.freeze(Object.defineProperty({__proto__:null,recipe:de,run:async({eventTarget:e,log:n,manager:t,own:a,registerCleanup:r})=>{r(t.subscribe(e=>{n("ÐодпиÑÑик менеджеÑа полÑÑил Ñнимок ÑоÑÑоÑниÑ",{activeModalId:e.activeModalId,openCount:e.openCount,revision:e.revision,stack:e.stack})}));const o=["opened","covered","revealed","closed","action-start","action-completed"].map(e=>`modal-manager-v2:${e}`),s=e=>n(`DOM event ${e.type}`,e.detail);o.forEach(n=>e?.addEventListener(n,s)),r(n=>o.forEach(n=>e?.removeEventListener(n,s)));const i=a(await t.prepare("ModalSuccess",{messages:["ÐакÑойÑе окно и ÑÑавниÑе запиÑи о ÑнимкаÑ
ÑоÑÑоÑÐ½Ð¸Ñ Ð¸ DOM-ÑобÑÑиÑÑ
в жÑÑнале кейÑа."]}));i.setText("title","MMV2-O01: наблÑдаемоÑÑÑ"),await t.open(i)}},Symbol.toStringTag,{value:"Module"})),me=Object.freeze({description:"ÐоказÑÐ²Ð°ÐµÑ Ð´Ð²Ð° меÑÑа Ð´Ð»Ñ Ð²ÑеменнÑÑ
даннÑÑ
: обÑÑÑ Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð½ÑÑ Ð¾Ð±Ð»Ð°ÑÑÑ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑа и Ñ
ÑанилиÑе оÑделÑного ÑкземплÑÑа окна.",expected:["ÐбÑие знаÑÐµÐ½Ð¸Ñ ÑиÑаÑÑÑÑ ÑолÑко по Ñвно Ð·Ð°Ð´Ð°Ð½Ð½Ð¾Ð¼Ñ Ð¸Ð¼ÐµÐ½Ð¸ облаÑÑи (manager scope), поÑÑÐ¾Ð¼Ñ ÑазнÑе инÑегÑаÑии не ÑмеÑиваÑÑ Ð´Ð°Ð½Ð½Ñе.","ÐнаÑÐµÐ½Ð¸Ñ ÑкземплÑÑа доÑÑÑÐ¿Ð½Ñ ÑолÑко ÑеÑез ÑооÑвеÑÑÑвÑÑÑий ModalInstance и намеÑенно не вÑ
одÑÑ Ð² пÑблиÑнÑй Ñнимок ÑоÑÑоÑниÑ.","ÐакÑÑÑие ÑдалÑÐµÑ Ð´Ð°Ð½Ð½Ñе ÑкземплÑÑа авÑомаÑиÑеÑки, а ÑбÑÐ¾Ñ ÐºÐµÐ¹Ñа Ñвно оÑиÑÐ°ÐµÑ ÑозданнÑÑ Ð¸Ð¼ обÑÑÑ Ð¾Ð±Ð»Ð°ÑÑÑ."],group:"СоÑÑоÑние и ÑобÑÑиÑ",id:"MMV2-O02",safety:"read-only",tags:["store","scope","cleanup"],title:"Ð¥ÑаниÑÑ Ð²ÑеменнÑе даннÑе в ÑазнÑÑ
облаÑÑÑÑ
",useWhen:"Ðогда одним вÑеменнÑм даннÑм нÑжно жиÑÑ Ð´Ð¾ закÑÑÑÐ¸Ñ ÐºÐ¾Ð½ÐºÑеÑного окна, а дÑÑгим â долÑÑе и под оÑвеÑÑÑвенноÑÑÑÑ Ð¸Ð½ÑегÑаÑии."}),pe=Object.freeze(Object.defineProperty({__proto__:null,recipe:me,run:async({log:e,manager:n,own:t,registerCleanup:a})=>{const r="modal-manager-v2-catalog:MMV2-O02";n.setStore(r,{recipeId:"MMV2-O02",source:"catalog"}),a(e=>n.clearStore(r));const o=t(await n.prepare("ModalSuccess",{messages:["ÐнаÑÐµÐ½Ð¸Ñ Ð²ÑеменнÑÑ
Ñ
ÑÐ°Ð½Ð¸Ð»Ð¸Ñ Ð½Ðµ попадаÑÑ Ð² пÑблиÑнÑй Ñнимок ÑоÑÑоÑÐ½Ð¸Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑа."]}));o.setText("title","MMV2-O02: облаÑÑи вÑеменнÑÑ
даннÑÑ
").setStore({localStep:1,owner:o.instanceId}).onDispose(n=>e("ÐблаÑÑÑ Ð´Ð°Ð½Ð½ÑÑ
ÑкземплÑÑа оÑиÑена пÑи его оÑвобождении")),await n.open(o),e("СÑавнение двÑÑ
облаÑÑей вÑеменнÑÑ
даннÑÑ
",{instanceStore:o.getStore(["localStep","owner"]),managerState:n.getState(),managerStore:n.getStore(r,["recipeId","source"])})}},Symbol.toStringTag,{value:"Module"})),ge=Object.freeze({description:"ÐÑкÑÑÐ²Ð°ÐµÑ ÑÑи ÑÑандаÑÑнÑÑ
окна ÑлоÑми, ÑÑÐ¾Ð±Ñ Ð²Ð¸Ð·ÑалÑно ÑÑавниÑÑ Ð²Ð°ÑианÑÑ ÑазмеÑÐµÐ½Ð¸Ñ sheet, dialog и dialog-lg.",expected:["Ð ÑÑеке показа одновÑеменно наÑ
одÑÑÑÑ ÑÑи ÑкземплÑÑа Ñ ÑазнÑми ваÑианÑами внеÑнего вида
1(presentation preset).","СнаÑала закÑÑваеÑÑÑ Ð²ÐµÑÑ
нее болÑÑое окно dialog-lg, заÑем ÑÑановÑÑÑÑ Ð´Ð¾ÑÑÑÐ¿Ð½Ñ dialog и sheet.","ÐеÑекÑÑÑÑе окна ÑоÑ
ÑанÑÑÑÑÑ Ð² DOM и ÑÐ²Ð¾Ñ ÑоÑÑоÑние; закÑÑÑие веÑÑ
него ÑÐ»Ð¾Ñ Ð½Ðµ ÑоздаÑÑ Ð¸Ñ
заново."],group:"ÐнеÑний вид",id:"MMV2-P01",safety:"read-only",tags:["sheet","dialog","dialog-lg"],title:"СÑавниÑÑ Ð²Ð°ÑианÑÑ ÑазмеÑÐµÐ½Ð¸Ñ Ð¾ÐºÐ¾Ð½",useWhen:"ЧÑÐ¾Ð±Ñ Ð²ÑбÑаÑÑ Ð¿Ð¾Ð´Ñ
одÑÑий ÑÐ°Ð·Ð¼ÐµÑ Ð¸ ÑаÑположение модалÑного окна и пÑовеÑиÑÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ неÑколÑкиÑ
ÑлоÑв."}),fe=Object.freeze(Object.defineProperty({__proto__:null,recipe:ge,run:async({log:e,manager:n,own:t})=>{const a=t(await n.prepare("ModalError",{messages:["Ðижний Ñлой иÑполÑзÑÐµÑ Ð²Ð°ÑÐ¸Ð°Ð½Ñ sheet."]}));a.setText("title","ÐаÑÐ¸Ð°Ð½Ñ ÑазмеÑениÑ: sheet");const r=t(await n.prepare("ModalPrompt",{details:"СÑедний Ñлой иÑполÑзÑÐµÑ Ð²Ð°ÑÐ¸Ð°Ð½Ñ dialog."}));r.setText("title","ÐаÑÐ¸Ð°Ð½Ñ ÑазмеÑениÑ: dialog").setPresentation({preset:"dialog",size:"sm"});const o=t(await n.prepare("ModalSuccess",{messages:["ÐеÑÑ
ний Ñлой иÑполÑзÑÐµÑ Ð²Ð°ÑÐ¸Ð°Ð½Ñ dialog-lg. ÐакÑÑвайÑе окна ÑвеÑÑ
Ñ Ð²Ð½Ð¸Ð·."]}));o.setText("title","ÐаÑÐ¸Ð°Ð½Ñ ÑазмеÑениÑ: dialog-lg").setPresentation({preset:"dialog-lg"}),await n.open(a),await n.open(r),await n.open(o),e("СÑек из ÑÑÑÑ
ваÑианÑов ÑазмеÑÐµÐ½Ð¸Ñ ÑÑоÑмиÑован",n.getState())}},Symbol.toStringTag,{value:"Module"})),Me=Object.freeze({description:"ÐÑкÑÑÐ²Ð°ÐµÑ Ð¾ÐºÐ½Ð¾, а заÑем менÑÐµÑ ÐµÐ³Ð¾ заголовок, ÑодеÑжимое, ÑазмеÑ, пÑавила закÑÑÑÐ¸Ñ Ð¸ пÑблиÑнÑй CSS-клаÑÑ.",expected:["ЧеÑез 700 Ð¼Ñ ÑодеÑжимое и заголовок менÑÑÑÑÑ, но instanceId оÑÑаÑÑÑÑ Ð¿Ñежним.","Ð Ð°Ð·Ð¼ÐµÑ Ð¸ пÑавила закÑÑÑÐ¸Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÑÑÑÑÑ Ð±ÐµÐ· повÑоÑного ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñа (remount).","ÐÑблиÑнÑй CSS-клаÑÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÐµÑ Ð²Ð¸Ð´Ð¸Ð¼ÑÑ ÑÐ°Ð¼ÐºÑ Ð¸ ÑдалÑеÑÑÑ Ð²Ð¼ÐµÑÑе Ñ ÑкземплÑÑом окна."],group:"ÐнеÑний вид",id:"MMV2-P02",safety:"read-only",tags:["reactivity","setProps","setClasses"],title:"ÐбновиÑÑ Ñже оÑкÑÑÑое окно",useWhen:"Ðогда оÑкÑÑÑое окно должно показаÑÑ Ð½Ð¾Ð²Ñе даннÑе, не ÑеÑÑÑ Ð²Ð²ÐµÐ´ÑннÑе знаÑÐµÐ½Ð¸Ñ Ð¸ дÑÑгое локалÑное ÑоÑÑоÑние компоненÑа."}),be=Object.freeze(Object.defineProperty({__proto__:null,recipe:Me,run:async({log:e,manager:n,own:t,wait:a})=>{const r=t(await n.prepare("ModalError",{details:"Ðбновление пÑоизойдÑÑ ÑеÑез 700 мÑ.",messages:["ÐаÑалÑное ÑодеÑжимое."]}));r.setText("title","MMV2-P02: наÑалÑное ÑоÑÑоÑние"),await n.open(r),await a(700)&&"closed"!==r.status&&(r.setText("title","MMV2-P02: окно обновлено без пеÑеÑозданиÑ").setProps({details:"ÐденÑиÑикаÑÐ¾Ñ ÑкземплÑÑа instanceId ÑоÑ
ÑанилÑÑ.",messages:["СодеÑжимое, ÑазмеÑ, пÑавила закÑÑÑÐ¸Ñ Ð¸ CSS-клаÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ñ Ð±ÐµÐ· пеÑеÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾ÐºÐ½Ð°."]}).setPresentation({dismiss:{backdrop:!0},size:"lg"}).setClasses({surface:"modal-manager-v2-catalog__demo-surface"}),e("ÐкземплÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð»Ñн без пеÑеÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñа",r.getState()))}},Symbol.toStringTag,{value:"Module"})),ye=(e,t,a,r)=>{const o=e=>{const n=t.getState();if(["closing","closed"].includes(n.status))return;if(n.busyActionId===a)return;const o=t.getAction(a);o&&o.disabled!==r.value&&t.setAction({id:a,disabled:r.value})},s=n(r,o,{flush:"sync"}),i=e.subscribe(o);t.onDispose(e=>{s(),i()})},he=Object.freeze({description:"Флаг isBlocked Ñ
ÑаниÑÑÑ Ð²Ð½Ðµ компоненÑа окна. Флажок менÑÐµÑ ÐµÐ³Ð¾ знаÑение, а watch обновлÑÐµÑ disabled кнопки ÑеÑез instance.setAction().",expected:["ÐÑи оÑкÑÑÑии Ñлажок ÑÑÑановлен, а кнопка «ÐодÑвеÑдиÑÑ» заблокиÑована.","СнимиÑе Ñлажок: кнопка ÑÑÐ°Ð½ÐµÑ Ð´Ð¾ÑÑÑпна. УÑÑановиÑе Ñнова: она заблокиÑÑеÑÑÑ Ð±ÐµÐ· пеÑеÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾ÐºÐ½Ð°.","ÐажмиÑе «ÐодÑвеÑдиÑÑ» и измениÑе Ñлаг во вÑÐµÐ¼Ñ Ð¿ÑовеÑки. ÐоÑле завеÑÑÐµÐ½Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° полÑÑÐ¸Ñ Ð¿Ð¾Ñледнее знаÑение Ñлага.","ÐакÑÑÑие окна ÑÐ½Ð¸Ð¼Ð°ÐµÑ Ð¿Ð¾Ð´Ð¿Ð¸Ñки; повÑоÑнÑй запÑÑк наÑÐ¸Ð½Ð°ÐµÑ ÐºÐµÐ¹Ñ Ñ Ð¸ÑÑ
одного ÑоÑÑоÑниÑ."],group:"ÐнеÑний вид",id:"MMV2-P03",safety:"read-only",tags:["setAction","disabled","boolean","watch"],title:"ÐлокиÑоваÑÑ ÐºÐ½Ð¾Ð¿ÐºÑ Ð¿Ð¾ ÑлагÑ",useWhen:"Ðогда доÑÑÑпноÑÑÑ Ð´ÐµÐ¹ÑÑÐ²Ð¸Ñ Ð·Ð°Ð²Ð¸ÑÐ¸Ñ Ð¾Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÑоÑмÑ, ÑезÑлÑÑаÑа пÑовеÑки или дÑÑгого ÑеакÑивного знаÑениÑ.",warnings:["disabled пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ boolean. ÐеÑедаÑа ref или ÑÑнкÑии вмеÑÑо знаÑÐµÐ½Ð¸Ñ Ð½Ðµ ÑоздаÑÑ Ð¿Ð¾Ð´Ð¿Ð¸ÑкÑ.","ÐÑполнÑÑÑийÑÑ action менÑÑÑ Ð½ÐµÐ»ÑзÑ. ÐодпиÑка на ÑоÑÑоÑние менеджеÑа пÑÐ¸Ð¼ÐµÐ½Ð¸Ñ Ð¾Ñложенное знаÑение поÑле его завеÑÑениÑ."]}),ve=Object.freeze(Object.defineProperty({__proto__:null,bindActionDisabled:ye,recipe:he,run:async({log:e,manager:n,own:s})=>{const i=o(!0),l=o("СнимиÑе Ñлажок, ÑÑÐ¾Ð±Ñ ÑазÑеÑиÑÑ Ð¿Ð¾Ð´ÑвеÑждение."),c=t(a({name:"RecipeDisabledAction",setup:e=>e=>r("div",[r(z,{params:{id:"mmv2-disabled-action-flag",model:i.value,texts:{label:"ÐлокиÑоваÑÑ ÐºÐ½Ð¾Ð¿ÐºÑ Ð¿Ð¾Ð´ÑвеÑждениÑ"}},onChange:e=>
1{i.value=Boolean(e.model)}}),r("p",`isBlocked: ${i.value}`),r("p",{role:"status"},l.value)])})),d=s(await n.prepare("ModalManagerV2CatalogApp/ModalRecipeContent",{contentComponent:c}));d.setText("title","MMV2-P03: кнопка завиÑÐ¸Ñ Ð¾Ñ Ñлага").setPresentation({size:"sm"}).setAction({id:"confirm",text:"ÐодÑвеÑдиÑÑ",role:"primary",closePolicy:"never"}).setActionHandler("confirm",async({flow:n,onCleanup:t,signal:a})=>(l.value="ÐÑовеÑка вÑполнÑеÑÑÑ. Ðожно измениÑÑ Ñлаг.",!(await new Promise(e=>{const n=setTimeout(n=>e(!0),1500),r=n=>e(!1);a.addEventListener("abort",r,{once:!0}),t(e=>{clearTimeout(n),a.removeEventListener("abort",r)})}))||a.aborted||(l.value="ÐÑовеÑка завеÑÑена. Ðнопка Ñнова завиÑÐ¸Ñ Ð¾Ñ Ñлага.",e("ÐодÑвеÑждение вÑполнено",{isBlocked:i.value})),n.stay())),ye(n,d,"confirm",i),await n.open(d),e("Ðнопка ÑвÑзана Ñ Ñлагом isBlocked",{instanceId:d.instanceId})}},Symbol.toStringTag,{value:"Module"})),we=Object.freeze({description:"ÐÑкÑÑÐ²Ð°ÐµÑ Ð½ÐµÐ¼Ð¾Ð´Ð°Ð»ÑнÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ ÑÑдом Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¾Ð¹ запÑÑка. СÑÑаниÑа оÑÑаÑÑÑÑ Ð´Ð¾ÑÑÑпной; положение пеÑеÑÑиÑÑваеÑÑÑ Ð¿Ñи пÑокÑÑÑке и изменении ÑазмеÑа.",expected:["Фон не заÑемнÑеÑÑÑ, пÑокÑÑÑка ÑÑÑаниÑÑ Ð´Ð¾ÑÑÑпна.","Escape и клик ÑнаÑÑжи закÑÑваÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ; Ñ ÐºÑÐ°Ñ ÑкÑана она менÑÐµÑ ÑÑоÑонÑ.","ÐовÑоÑнÑй запÑÑк ÑоздаÑÑ Ð½Ð¾Ð²Ñй ÑкземплÑÑ Ð¿Ð¾Ñле закÑÑÑÐ¸Ñ Ð¿ÑедÑдÑÑего."],group:"ÐнеÑний вид",id:"MMV2-P04",safety:"read-only",tags:["anchored-dialog","popover","modal: false"],title:"ÐемодалÑÐ½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»Ñ Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸",useWhen:"ÐÐ»Ñ Ð¿Ð°Ð»Ð¸ÑÑ Ð¸ неболÑÑиÑ
вÑпомогаÑелÑнÑÑ
ÑоÑм на ÑÑÑаниÑе."}),Oe=Object.freeze(Object.defineProperty({__proto__:null,recipe:we,run:async({anchor:e,log:n,manager:t,own:a})=>{const r=a(await t.prepare("ModalPrompt",{details:"ÐÑокÑÑÑиÑе ÑÑÑаниÑÑ: Ð¿Ð°Ð½ÐµÐ»Ñ ÑледÑÐµÑ Ð·Ð° кнопкой и оÑÑаÑÑÑÑ Ð²Ð½ÑÑÑи видимой облаÑÑи."}));r.setText("title","ÐемодалÑÐ½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»Ñ").setPresentation({preset:"anchored-dialog",modal:!1,size:"sm"}).setAnchor(e),await t.open(r),n("ÐÐ°Ð½ÐµÐ»Ñ Ð¾ÑкÑÑÑа без блокиÑовки ÑÑÑаниÑÑ",r.getState())}},Symbol.toStringTag,{value:"Module"})),Fe=t(a({props:{openPanel:l(Function,null,!0)},setup:e=>{const{$b:n}=s("b-modal-v2"),t=o(0);return a=>r("div",[r("p",`СÑÑÑÑик ÑодиÑелÑ: ${t.value}`),r("div",{class:n`,actions`},[r(i,{buttonText:"ÐзмениÑÑ ÑодиÑелÑ",type:"secondary",onAction:e=>{t.value++}}),r(i,{buttonText:"ÐÑкÑÑÑÑ Ð´Ð¾ÑеÑнÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ",type:"secondary",onAction:n=>e.openPanel(n.event.currentTarget)})])])}})),Se=Object.freeze({description:"ÐÑкÑÑÐ²Ð°ÐµÑ Ð¾Ð±ÑÑное окно, внÑÑÑи коÑоÑого можно вÑзваÑÑ Ð½ÐµÐ¼Ð¾Ð´Ð°Ð»ÑнÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ. РодиÑÐµÐ»Ñ ÑоÑ
ÑанÑÐµÑ ÑоÑÑоÑние, а ÑÑÑаниÑа оÑÑаÑÑÑÑ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñованной ÑодиÑелÑÑким окном.",expected:["СÑÑÑÑик ÑодиÑÐµÐ»Ñ Ð¼Ð¾Ð¶Ð½Ð¾ менÑÑÑ Ð¿Ñи оÑкÑÑÑой панели: модалÑноÑÑÑ ÑодиÑÐµÐ»Ñ Ð½Ðµ ÑÑиливаеÑÑÑ.","ÐеÑвÑй Escape закÑÑÐ²Ð°ÐµÑ Ð¿Ð°Ð½ÐµÐ»Ñ, ÑледÑÑÑий â ÑодиÑелÑÑкое окно.","ÐÑеÑÑик ÑодиÑÐµÐ»Ñ Ð·Ð°ÐºÑÑÐ²Ð°ÐµÑ Ð¾Ð±Ð° ÑкземплÑÑа; доÑеÑнÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ Ð¿Ð¾Ð»ÑÑÐ°ÐµÑ Ð¿ÑиÑÐ¸Ð½Ñ owner-closed."],group:"ÐнеÑний вид",id:"MMV2-P05",safety:"read-only",tags:["anchored-dialog","setOwner","nested","modal: false"],title:"ÐÐ°Ð½ÐµÐ»Ñ Ð²Ð½ÑÑÑи модалÑного окна",useWhen:"ÐÐ»Ñ Ð¿Ð°Ð»Ð¸ÑÑÑ Ð¸Ð»Ð¸ вÑпомогаÑелÑной ÑоÑÐ¼Ñ Ð² Ñже оÑкÑÑÑом диалоге."}),je=Object.freeze(Object.defineProperty({__proto__:null,recipe:Se,run:async({log:e,manager:n,own:t})=>{let a=null;const r=t(await n.prepare("ModalManagerV2CatalogApp/ModalRecipeContent",{contentComponent:Fe,contentProps:{openPanel:async o=>{try{if(a&&"closed"!==a.status)return void(await a.close());a=t(await n.prepare("ModalPrompt",{details:"РодиÑÐµÐ»Ñ Ð¾ÑÑаÑÑÑÑ Ð´Ð¾ÑÑÑпнÑм. ÐÑа Ð¿Ð°Ð½ÐµÐ»Ñ Ð¿ÑÐ¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ ÐµÐ¼Ñ."})),a.clearActions().setText("title","ÐоÑеÑнÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ").setPresentation({preset:"anchored-dialog",modal:!1,size:"sm",dismiss:{outside:!1}}).setAnchor(o).setOwner(r),await n.open(a)}catch(s){a&&"closed"!==a.status&&await a.close(),e("ÐÐ°Ð½ÐµÐ»Ñ Ð½Ðµ оÑкÑÑлаÑÑ",{message:s.message},"error")}}}}));r.setText("title","РодиÑелÑÑкое окно"),await n.open(r)}},Symbol.toStringTag,{value:"Module"})),Ie=Object.freeze({description:"ÐÑполÑзÑÐµÑ ÑÑ Ð¶Ðµ пÑивÑÐ·ÐºÑ Ðº кнопке, но оÑкÑÑÐ²Ð°ÐµÑ Ð¿Ð¾Ð»Ð½Ð¾ÑеннÑй блокиÑÑÑÑий диалог ÑеÑез presentation.modal: true.",expected:["Ðкно пÑивÑзано к кнопке, Ñон заÑемнÑн и недоÑÑÑпен.","ФокÑÑ ÑдеÑживаеÑÑÑ Ð² диалоге; Escape и кÑеÑÑик закÑÑваÑÑ Ð¾ÐºÐ½Ð¾.","ÐоÑле закÑÑÑÐ¸Ñ Ð²Ð¾ÑÑÑанавливаÑÑÑÑ Ð¿ÑокÑÑÑка и ÑокÑÑ."],group:"ÐнеÑний вид",id:"MMV2-P06",safety:"read-only",tags:["anchored-dialog","modal: true"],title:"ÐодалÑное окно Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸",useWhen:"Ðогда диалог нÑжно ÑаÑположиÑÑ ÑÑдом Ñ Ð¸ÑÑоÑником дейÑÑÐ²Ð¸Ñ Ð¸ вÑеменно заблокиÑоваÑÑ Ð¾ÑÑалÑнÑÑ ÑÑÑаниÑÑ."}),Re=Object.freeze(Object.defineProperty({__proto__:null,recipe:Ie,run:async({anchor:e,log:n,manager:t,own:a})=>{const r=a(await t.prepare("ModalPrompt",{details:"ÐодалÑноÑÑÑ Ð·Ð°Ð´Ð°ÑÑÑÑ Ð¾ÑделÑно Ð¾Ñ ÑаÑÐ¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¾ÐºÐ½Ð°."}));r.setText("title","ÐÑивÑзаннÑй модалÑнÑй диалог").setPresentation({preset:"anchored-dialog",modal:!0,size:"sm"}).setAnchor(e),await t.open(r),n("ÐÑкÑÑÑ Ð¼Ð¾Ð´Ð°Ð»ÑнÑй диалог Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸",r.getState())}},Symbol.toStringTag,{value:"Module"})),xe=Object.freeze({description:"ÐÑовеÑÑеÑ, ÑÑо каÑалог подклÑÑÑн к гоÑÐ¾Ð²Ð¾Ð¼Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑÑ Ð¿Ð¾ клÑÑÑ globalThis.infotecs.ModalManagerV2 и не ÑоздаÑÑ ÐµÐ³Ð¾ копиÑ.",expected:["ÐлÑÑ globalThis.infotecs.ModalManagerV2 Ñказ
1ÑÐ²Ð°ÐµÑ Ð½Ð° ÑÐ¾Ñ Ð¶Ðµ обÑекÑ, коÑоÑÑй иÑполÑзÑÐµÑ ÐºÐ°Ñалог.","СÑаÑÑй Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ V1 оÑÑаÑÑÑÑ Ð´Ð¾ÑÑÑпен оÑделÑно по клÑÑÑ globalThis.infotecs.ModalManager.","getState() возвÑаÑÐ°ÐµÑ Ð½ÐµÐ¸Ð·Ð¼ÐµÐ½ÑемÑй Ñнимок: внеÑний код не Ð¼Ð¾Ð¶ÐµÑ Ð¿ÐµÑепиÑаÑÑ ÐµÐ³Ð¾ Ð¿Ð¾Ð»Ñ Ð¸Ð»Ð¸ ÑпиÑок ÑкземплÑÑов."],group:"ÐодклÑÑение и API",id:"MMV2-R01",safety:"read-only",tags:["ready","global","snapshot"],title:"ÐÑовеÑиÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑÑение к обÑÐµÐ¼Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑÑ",useWhen:"ÐÑи добавлении новой ÑоÑки вÑ
ода, ÑÑÐ¾Ð±Ñ ÑбедиÑÑÑÑ: она ждÑÑ Ð·Ð°Ð¿ÑÑк пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸ иÑполÑзÑÐµÑ Ð¾Ð±Ñий менеджеÑ, а не ÑоздаÑÑ Ð²ÑоÑой."}),_e=Object.freeze(Object.defineProperty({__proto__:null,recipe:xe,run:async({globalTarget:e,log:n,manager:t,namespaceKey:a})=>{const r=await t.whenReady(),o=e[a]??{},s=t.getState();n("ÐÑовеÑÐµÐ½Ñ Ð³Ð¾ÑовноÑÑÑ Ð¸ глобалÑнÑй клÑÑ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑа",{immutableInstances:Object.isFrozen(s.instances),immutableState:Object.isFrozen(s),legacyAvailable:Boolean(o.ModalManager),readyIdentity:r===t,v2GlobalIdentity:o.ModalManagerV2===t}),n("ТекÑÑий Ñнимок ÑоÑÑоÑÐ½Ð¸Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑа",s)}},Symbol.toStringTag,{value:"Module"})),Ce=Object.freeze({description:"ÐоÑледоваÑелÑно вÑзÑÐ²Ð°ÐµÑ prepare(), наÑÑÑÐ°Ð¸Ð²Ð°ÐµÑ Ð¿Ð¾Ð´Ð³Ð¾ÑовленнÑй ÑкземплÑÑ ÑепоÑкой меÑодов и пеÑедаÑÑ ÐµÐ³Ð¾ в open().",expected:["ÐаждÑй меÑод наÑÑÑойки возвÑаÑÐ°ÐµÑ ÑÐ¾Ñ Ð¶Ðµ ModalInstance, поÑÑÐ¾Ð¼Ñ Ð²ÑÐ·Ð¾Ð²Ñ Ð¼Ð¾Ð¶Ð½Ð¾ обÑединÑÑÑ Ð² ÑепоÑкÑ.","open(instance) возвÑаÑÐ°ÐµÑ ÑÐ¾Ñ Ð¶Ðµ обÑÐµÐºÑ Ð¸ показÑÐ²Ð°ÐµÑ ÑооÑвеÑÑÑвÑÑÑее окно.","ÐоÑле закÑÑÑÐ¸Ñ ÑÑаÑÑÑ ÑкземплÑÑа ÑÑановиÑÑÑ closed; повÑоÑно иÑполÑзоваÑÑ Ð·Ð°Ð²ÐµÑÑÑннÑй ÑкземплÑÑ Ð½ÐµÐ»ÑзÑ."],group:"ÐодклÑÑение и API",id:"MMV2-R02",safety:"read-only",tags:["prepare","fluent","identity"],title:"ÐодгоÑовиÑÑ, наÑÑÑоиÑÑ Ð¸ оÑкÑÑÑÑ Ð¾ÐºÐ½Ð¾",useWhen:"Ðогда ÑодеÑжимое, кнопки и внеÑний вид окна нÑжно полноÑÑÑÑ Ð½Ð°ÑÑÑоиÑÑ Ð´Ð¾ пеÑвого показа полÑзоваÑелÑ."}),Ae=Object.freeze(Object.defineProperty({__proto__:null,recipe:Ce,run:async({log:e,manager:n,own:t})=>{const a=t(await n.prepare("ModalSuccess",{messages:["ÐкземплÑÑ Ð¿Ð¾Ð´Ð³Ð¾Ñовлен до показа."]})),r=a.setText("title","MMV2-R02: подгоÑовленнÑй ÑкземплÑÑ").setPresentation({preset:"dialog",size:"sm"}).setAction({id:"close",role:"primary",text:"ÐакÑÑÑÑ ÐºÐµÐ¹Ñ"}),o=await n.open(a);e("ÐÑовеÑено ÑоÑ
Ñанение одного ÑкземплÑÑа пÑи наÑÑÑойке и оÑкÑÑÑии",{fluentIdentity:r===a,instanceId:a.instanceId,openIdentity:o===a,state:a.getState()})}},Symbol.toStringTag,{value:"Module"})),Te="<template>\n <div :class=\"$b`,content`\">\n <component\n :is=\"contentComponent\"\n v-bind=\"contentProps\" />\n </div>\n</template>\n\n<script>\n// classes\nimport { defineModalConfig } from '@classes/ModalManager/index.js';\n\n\nexport const modalConfig = defineModalConfig({\n actionPreset: 'close',\n presentation: { preset: 'dialog' },\n});\n\nexport default { name: 'ModalRecipeContent' };\n<\/script>\n\n<script setup>\n// composables\nimport { useBEM } from '@cms/useBEM';\n\n\n//================================= composables\nconst { $b } = useBEM('b-modal-v2');\n\n\n//================================= props\ndefineProps({\n contentComponent: {\n type: [Object, Function],\n required: true,\n },\n contentProps: {\n type: Object,\n default: _ => ({}),\n },\n});\n<\/script>\n",Pe=Object.freeze(["code","em","li","ol","p","strong","ul"]),Ee=e=>D.sanitize(e,{ALLOWED_ATTR:[],ALLOWED_TAGS:Pe,ALLOW_ARIA_ATTR:!1,ALLOW_DATA_ATTR:!1}),Ve=t(a({name:"RecipeSafeHtmlContent",props:{html:{type:String,default:""}},setup:e=>{const n=c(n=>Ee(e.html));return e=>r("div",{"data-test":"mmv2-recipe-html-content",innerHTML:n.value})}})),ze=Object.freeze([Object.freeze({label:"Vue-оболоÑка пÑоизволÑного ÑодеÑжимого",source:Te})]),De=Object.freeze({description:"ÐеÑедаÑÑ HTML-ÑÑÑÐ¾ÐºÑ Ð² Vue-компоненÑ, коÑоÑÑй оÑиÑÐ°ÐµÑ ÐµÑ Ð½ÐµÐ¿Ð¾ÑÑедÑÑвенно пеÑед HTML-sink Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ DOMPurify и ÑÑÑогого ÑпиÑка ÑазÑеÑÑннÑÑ
Ñегов.",expected:["ÐбзаÑ, ÑпиÑок, вÑделение и inline code оÑобÑажаÑÑÑÑ ÐºÐ°Ðº ÑазмеÑка.","img, обÑабоÑÑик onerror, ÑÑÑлка и javascript: URL не попадаÑÑ Ð² DOM; ÑекÑÑ ÑÑÑлки оÑÑаÑÑÑÑ ÑиÑаемÑм.","ÐÐµÐ½ÐµÐ´Ð¶ÐµÑ Ð¿Ð¾Ð»ÑÑÐ°ÐµÑ Ñже довеÑеннÑй Vue-компоненÑ; ÐºÐµÐ¹Ñ Ð½Ðµ ÑегиÑÑÑиÑÑÐµÑ runtime modal и не ÑоздаÑÑ Ð²ÑоÑой manager."],group:"ÐÑоизволÑное ÑодеÑжимое",id:"MMV2-X01",safety:"read-only",tags:["HTML","DOMPurify","XSS","allowlist"],title:"ÐоказаÑÑ Ð¾ÑиÑенное HTML-ÑодеÑжимое",useWhen:"ТолÑко когда бизнеÑ-ÑÑебование дейÑÑвиÑелÑно ÑÑебÑÐµÑ ÑазмеÑÐºÑ Ð¸Ð· ÑÑÑоки. ÐÐ»Ñ Ð¾Ð±ÑÑного ÑекÑÑа иÑполÑзÑйÑе инÑеÑполÑÑÐ¸Ñ Vue, а Ð´Ð»Ñ ÑÑÑÑкÑÑÑиÑованного инÑеÑÑейÑа â Vue-компоненÑ.",warnings:["v-html и innerHTML ÑвлÑÑÑÑÑ XSS-sink: авÑоÑизаÑÐ¸Ñ ÑÑÑаниÑÑ Ð¸ оÑÑÑÑÑÑвие Ñега script не делаÑÑ Ð½ÐµÐ¿ÑовеÑеннÑÑ ÑÑÑÐ¾ÐºÑ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñной.","ÐÑиÑаÑÑ Ð½Ñжно Ñ Ñамого sink. ÐоÑле DOMPurify нелÑÐ·Ñ Ð´Ð¾Ð¿Ð¸ÑÑваÑÑ ÑазмеÑÐºÑ ÑÑÑоками или пеÑедаваÑÑ ÑезÑлÑÑÐ°Ñ ÐºÐ¾Ð´Ñ, коÑоÑÑй Ñнова менÑÐµÑ HTML.","Allowlist ÑÑого кейÑа намеÑенно не ÑазÑеÑÐ°ÐµÑ ÑÑÑлки, изобÑажениÑ, ÑÑили и лÑбÑе аÑÑибÑÑÑ; ÑаÑÑиÑение ÑпиÑка ÑÑебÑÐµÑ Ð¾ÑделÑного security review."]}),Le=Object.freeze(Object.defineProperty({__proto__:null,recipe:De,run:async({log:e,manager:n,own:t})=>{const a=t(await n.prepare("ModalManagerV2CatalogApp/ModalRecipeContent",{contentComponent:Ve,contentProps:{html:'\n <p><strong>РазÑеÑÑÐ½Ð½Ð°Ñ ÑазмеÑка</strong> оÑÑаÑÑÑÑ Ð² окне.</p>\n <ul>\n <li>СпиÑки, <em>вÑделение</em> и <code>inline code</code>.</li>\n </ul>\n <img src="missing" onerror="alert(\'xss\')">\n <a href="javascript:alert(\'xss\')">ÐпаÑÐ½Ð°Ñ ÑÑÑлка ÑÑановиÑÑÑ Ð¾Ð±ÑÑнÑм ÑекÑÑом.</a>\n'}}));a.setText("title","MMV2-X01: оÑиÑенное HTML-ÑодеÑжимое").setPresentation({size:"sm"}),await n.open(a),e("HTML пеÑедан в ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ñ Ð¾ÑиÑÑкой Ñ sink",{allowedTags:Pe,instanceId:a.instanceId})},sanitizeRecipeHtml:Ee,supportingSources:ze},Symbol.toStringTag,{value:"Module"})),ke=t(a({name:"RecipeJsConfiguredContent",props:{description:{type:String,default:""},phase:{type:String,default:""}},setup:e=>n=>r("div",{"data-test":"mmv2-recipe-js-content"},[r("p",[r("strong","СоÑÑоÑние: "),e.phase]),r("p",e.description)])})),Ne=(e,n)=>e.setText("title","MMV2-X02: Ñело изменено ÑеÑез public API").setProps({contentProps:n}),Ge=Object.freeze([Object.freeze({label:"Vue-оболоÑка пÑоизволÑного ÑодеÑжимого",source:Te})]),$e=Object.freeze({description:"ÐеÑедаÑÑ ModalInstance в обÑÑнÑÑ JS-ÑÑнкÑиÑ. ФÑнкÑÐ¸Ñ Ð¼ÐµÐ½ÑÐµÑ props вложенного компоненÑа ÑеÑез setProps() и заголовок ÑеÑез setText(), не полÑÑÐ°Ñ ÑÑÑÐ»ÐºÑ Ð½Ð° DOM.",expected:["Ðкно оÑкÑÑваеÑÑÑ Ñ Ð½Ð°ÑалÑнÑм ÑекÑÑом и ÑеÑез 700 Ð¼Ñ Ð¿Ð¾ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð½Ð¾Ð²Ð¾Ðµ ÑоÑÑоÑние.","instanceId и локалÑнÑй Vue-ÑкземплÑÑ ÑоÑ
ÑанÑÑÑÑÑ: manager обновлÑÐµÑ props без remount.","ФÑнкÑÐ¸Ñ Ð¸ÑполÑзÑÐµÑ ÑолÑко пÑблиÑнÑй ModalInstance API; querySelector, innerHTML и ÑÑÑÐ½Ð°Ñ Ð·Ð°Ð¼ÐµÐ½Ð° DOM не нÑжнÑ."],group:"ÐÑоизволÑное ÑодеÑжимое",id:"MMV2-X02",safety:"read-only",tags:["JavaScript","setProps","
1setText","no DOM"],title:"ÐзмениÑÑ Ñело JS-ÑÑнкÑией ÑеÑез API",useWhen:"Ðогда даннÑе пÑиÑ
одÑÑ Ð¿Ð¾Ñле оÑкÑÑÑÐ¸Ñ Ð¾ÐºÐ½Ð° или обÑий configurator должен обновиÑÑ Ð¿ÑедÑÑавление, ÑоÑ
Ñанив lifecycle, ÑеакÑивноÑÑÑ Ð¸ локалÑное ÑоÑÑоÑние Vue-компоненÑа.",warnings:["ÐÑÑÐ¼Ð°Ñ Ð¿Ñавка DOM обÑ
Ð¾Ð´Ð¸Ñ Vue render tree, Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð·Ð°ÑÑÑÑа ÑледÑÑÑим render и ÑоздаÑÑ XSS-, focus- и cleanup-ÑиÑки.","ФÑнкÑÐ¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° полÑÑаÑÑ ModalInstance или пÑедмеÑнÑй callback, а не HTMLElement внÑÑÑенней повеÑÑ
ноÑÑи окна."]}),Ue=Object.freeze(Object.defineProperty({__proto__:null,recipe:$e,run:async({log:e,manager:n,own:t,wait:a})=>{const r=t(await n.prepare("ModalManagerV2CatalogApp/ModalRecipeContent",{contentComponent:ke,contentProps:{description:"JS-конÑигÑÑаÑÐ¾Ñ ÐµÑÑ Ð½Ðµ пÑименил обновление.",phase:"наÑалÑное"}}));r.setText("title","MMV2-X02: иÑÑ
одное Ñело").setPresentation({size:"sm"}),await n.open(r),await a(700)&&"closed"!==r.status&&(Ne(r,{description:"ФÑнкÑÐ¸Ñ Ð²Ñзвала setProps({ contentProps }) Ñ Ñого же ModalInstance.",phase:"обновлÑнное"}),e("JS-ÑÑнкÑÐ¸Ñ Ð¾Ð±Ð½Ð¾Ð²Ð¸Ð»Ð° Ñело ÑеÑез ModalInstance API",r.getState()))},supportingSources:Ge,updateRecipeBody:Ne},Symbol.toStringTag,{value:"Module"})),Be="ModalManagerV2CatalogApp/ModalRecipeContent",We=t(a({name:"RecipeVueContent",props:{label:{type:String,default:""}},setup:e=>{const n=o(0);return t=>r("div",{"data-test":"mmv2-recipe-vue-content"},[r("p",e.label),r("p",`ÐокалÑнÑй ÑÑÑÑÑик компоненÑа: ${n.value}`),r(i,{attributes:{type:"button"},buttonText:"УвелиÑиÑÑ ÑÑÑÑÑик",onAction:e=>{n.value+=1},type:"secondary"})])}})),qe=Object.freeze([Object.freeze({label:"Vue-оболоÑка пÑоизволÑного ÑодеÑжимого",source:Te})]),He=Object.freeze({description:"ÐеÑедаÑÑ version-controlled Vue-ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ ÐºÐ°Ðº prop каÑаложной modal-оболоÑки. ÐÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ ÑодеÑÐ¶Ð¸Ñ ÑобÑÑвенное ÑоÑÑоÑние, обÑабоÑÑик ÑобÑÑÐ¸Ñ Ð¸ UiButton из дизайн-ÑиÑÑемÑ.",expected:["ÐнÑÑÑи окна оÑобÑажаеÑÑÑ Vue-ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð¸ кнопка из ui-list.","Ðаждое нажаÑие ÑвелиÑÐ¸Ð²Ð°ÐµÑ Ð»Ð¾ÐºÐ°Ð»ÑнÑй ref без обÑаÑÐµÐ½Ð¸Ñ Ðº manager и без remount окна.","ÐакÑÑÑие окна ÑниÑÑÐ¾Ð¶Ð°ÐµÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ñй Vue-ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð²Ð¼ÐµÑÑе Ñ ÐµÐ³Ð¾ локалÑнÑм ÑоÑÑоÑнием."],group:"ÐÑоизволÑное ÑодеÑжимое",id:"MMV2-X03",safety:"read-only",tags:["Vue","dynamic component","markRaw","UiButton"],title:"ÐÑкÑÑÑÑ Ð¾ÐºÐ½Ð¾ Ñ Vue-компоненÑом",useWhen:"Ðогда ÑÐµÐ»Ñ Ð¾ÐºÐ½Ð° нÑÐ¶Ð½Ñ ÑоÑмÑ, ÑеакÑивное ÑоÑÑоÑние, ÑобÑÑÐ¸Ñ Ð¸Ð»Ð¸ пеÑеиÑполÑзÑемÑе UI-компоненÑÑ. ÐÑо оÑновной пÑÑÑ Ð´Ð»Ñ Ñложного ÑодеÑжимого.",warnings:["Vue-ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ ÑвлÑеÑÑÑ Ð¸ÑполнÑемÑм кодом Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¼Ð¾ÑиÑми пÑиложениÑ: пеÑедаваÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ ÑолÑко довеÑеннÑй код из ÑбоÑки, а не Ñаблон или ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð¸Ð· оÑвеÑа API.","Modal host не подклÑÑÐ°ÐµÑ router, Pinia и дÑÑгие app plugins авÑомаÑиÑеÑки; завиÑимоÑÑи компоненÑа Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ ÑвнÑми."]}),Xe=Object.freeze(Object.defineProperty({__proto__:null,recipe:He,run:async({log:e,manager:n,own:t})=>{const a=t(await n.prepare(Be,{contentComponent:We,contentProps:{label:"ÐÑÐ¾Ñ Ð±Ð»Ð¾Ðº полноÑÑÑÑ Ð¾ÑÑиÑован пеÑеданнÑм Vue-компоненÑом."}}));a.setText("title","MMV2-X03: пÑоизволÑнÑй Vue-компоненÑ").setPresentation({size:"sm"}),await n.open(a),e("Vue-ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð¾ÑкÑÑÑ ÑеÑез convention-based modal ID",{instanceId:a.instanceId,modalId:Be})},supportingSources:qe},Symbol.toStringTag,{value:"Module"})),Je="<template>\n <div :class=\"$b`,content`\">\n <FormRuntime\n v-bind=\"$props\"\n :close=\"close\"\n :message-class=\"$b`,message`\" />\n </div>\n</template>\n\n<script>\n// classes\nimport { defineModalConfig } from '@classes/ModalManager/index.js';\n\n\nexport const modalConfig = defineModalConfig({\n actionPreset: 'none',\n presentation: { preset: 'dialog' },\n});\n\nexport default { name: 'ModalForm' };\n<\/script>\n\n<script setup>\n// composables\nimport { useBEM } from '@cms/useBEM';\nimport { useModalInstance } from '@cmp/ModalManagerV2/composables/useModalInstance.js';
1\n\n// components\nimport FormRuntime from '@cmp/FormManager/FormRuntime.vue';\n\n\n//================================= composables\nconst { $b } = useBEM('b-modal-v2');\nconst instance = useModalInstance();\nif (!instance) throw new TypeError('ModalForm requires a ModalInstance');\nconst close = result => instance.close(result);\n\n\n//================================= props\ndefineProps({\n dataForm: { type: Object, required: true },\n destroyForm: { type: Function, default: null },\n fireContext: { type: Boolean, default: false },\n functions: { type: Object, default: _ => ({}) },\n onSubmit: { type: Function, default: null },\n onTrigger: { type: Function, default: null },\n updateData: { type: Object, default: null },\n});\n\n\n<\/script>\n",Ke="Footer/NewsletterSubscription",Ye=Object.freeze([Object.freeze({label:"ÐÑблиÑнÑй FormManager facade",source:"import { FormInstance } from './FormInstance.js';\nimport {\n FORM_MANAGER_ERROR_CODES,\n formManagerError,\n} from './FormManagerError.js';\n\n\nconst assertFormId = value => {\n if (typeof value !== 'string' || value.trim() === '') {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_ARGUMENT,\n 'Form id must be a non-empty string',\n );\n }\n return value;\n};\n\nconst normalizeFormPath = value => {\n if (typeof value !== 'string' || value.trim() === '') {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_ARGUMENT,\n 'Form path must be a non-empty string',\n );\n }\n return value.trim().replaceAll('\\\\', '/');\n};\n\nconst assertObject = (value, label) => {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_ARGUMENT,\n `${label} must be an object`,\n );\n }\n return value;\n};\n\nconst assertSource = value => {\n if (\n typeof value !== 'function'\n && (!value || typeof value !== 'object' || Array.isArray(value))\n ) {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_ARGUMENT,\n 'Form scheme must be an object or a factory function',\n );\n }\n return value;\n};\n\nconst invalidRuntime = (id, message) => formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_FORM_RUNTIME,\n `Form \"${id}\" ${message}`,\n { id },\n);\n\nconst assertNoDataUpdate = (value, createError) => {\n if (Object.prototype.hasOwnProperty.call(value, 'dataUpdate')) {\n throw createError('dataUpdate is not supported; use updateData');\n }\n return value;\n};\n\nconst assertRuntimeFunction = (id, value, label) => {\n if (value !== null && value !== undefined && typeof value !== 'function') {\n throw invalidRuntime(id, `${label} must be a function`);\n }\n return value ?? null;\n};\n\nconst assertRuntimeObject = (id, value, label, { nullable = false } = {}) => {\n if (nullable && (value === null || value === undefined)) return null;\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw invalidRuntime(id, `${label} must be an object`);\n }\n return value;\n};\n\nconst assertRuntimeTitle = (id, value) => {\n if (value === null || value === undefined) return '';\n if (typeof value !== 'string') throw invalidRuntime(id, 'title must be a string');\n return value;\n};\n\nconst normalizeCatalog = catalog => {\n if (catalog instanceof Map) return new Map(catalog);\n if (!catalog || typeof catalog !== 'object' || Array.isArray(catalog)) {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_ARGUMENT,\n 'Form catalog must be an object or a Map',\n );\n }\n return new Map(Object.entries(catalog));\n};\n\nconst normalizePathCatalog = catalog => new Map(\n [...normalizeCatalog(catalog)]\n .map(([path, loader]) => [normalizeFormPath(path), loader]),\n);\n\nconst unwrapLoadedSource = source => {\n if (!source || typeof source !== 'object' || Array.isArray(source)) return source;\n if (Object.prototype.hasOwnProperty.call(source, 'default')) {\n return source.default;\n }\n if (\n source[Symbol.toStringTag] === 'Module'\n && Object.prototype.hasOwnProperty.call(source, 'form')\n ) {\n return source.form;\n }\n return source;\n};\n\nconst normalizeDefinition = definition => {\n if (\n definition?.form\n && definition?.functions\n && definition.dataForm === undefined\n ) {\n return {\n dataForm: definition.form,\n functions: definition.functions,\n };\n }\n if (definition?.params && definition.dataForm === undefined) {\n return { dataForm: definition };\n }\n return definition;\n};\n\nconst overrideValue = (overrides, key, fallback) =>\n Object.prototype.hasOwnProperty.call(overrides, key)\n ? overrides[key]\n : fallback;\n\nconst normalizeRuntime = (id, definition, overrides) => {\n const runtime = assertNoDataUpdate(\n assertRuntimeObject(\n id,\n normalizeDefinition(definition),\n 'runtime',\n ),\n message => invalidRuntime(id, message),\n );\n const dataForm = assertRuntimeObject(\n id,\n overrideValue(overrides, 'dataForm', runtime.dataForm),\n 'dataForm',\n );\n const formParams = assertRuntimeObject(id, dataForm.params, 'dataForm.params');\n if (typeof formParams.id !== 'string' || formParams.id.trim() === '') {\n throw invali
1dRuntime(id, 'dataForm.params.id must be a non-empty string');\n }\n\n const runtimeFunctions = runtime.functions ?? {};\n const overrideFunctions = overrides.functions ?? {};\n assertRuntimeObject(id, runtimeFunctions, 'functions');\n assertRuntimeObject(id, overrideFunctions, 'store functions');\n\n const runtimePresentation = runtime.presentation ?? {};\n const overridePresentation = overrides.presentation ?? {};\n assertRuntimeObject(id, runtimePresentation, 'presentation');\n assertRuntimeObject(id, overridePresentation, 'store presentation');\n\n const fireContext = overrideValue(\n overrides,\n 'fireContext',\n runtime.fireContext ?? false,\n );\n if (typeof fireContext !== 'boolean') {\n throw invalidRuntime(id, 'fireContext must be a boolean');\n }\n\n return Object.freeze({\n dataForm,\n fireContext,\n functions: {\n ...runtimeFunctions,\n ...overrideFunctions,\n },\n mount: overrideValue(overrides, 'mount', runtime.mount ?? null),\n onMount: assertRuntimeFunction(\n id,\n overrideValue(overrides, 'onMount', runtime.onMount),\n 'onMount',\n ),\n onSubmit: assertRuntimeFunction(\n id,\n overrideValue(overrides, 'onSubmit', runtime.onSubmit),\n 'onSubmit',\n ),\n onTrigger: assertRuntimeFunction(\n id,\n overrideValue(overrides, 'onTrigger', runtime.onTrigger),\n 'onTrigger',\n ),\n presentation: {\n ...runtimePresentation,\n ...overridePresentation,\n },\n title: assertRuntimeTitle(\n id,\n overrideValue(overrides, 'title', runtime.title),\n ),\n updateData: assertRuntimeObject(\n id,\n overrideValue(overrides, 'updateData', runtime.updateData),\n 'updateData',\n { nullable: true },\n ),\n });\n};\n\nexport class FormManager {\n static Form = null;\n\n #catalog = null;\n #forms = new Map();\n #loadRuntime = null;\n #loadedSources = new Map();\n #pathCatalog = null;\n #pathRegistrations = new Map();\n #runtimeReady = null;\n #sequence = 0;\n #stores = new Map();\n\n constructor({\n catalog = {},\n loadRuntime = async _ => ({ mount: null }),\n pathCatalog = {},\n } = {}) {\n if (typeof loadRuntime !== 'function') {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_ARGUMENT,\n 'FormManager loadRuntime must be a function',\n );\n }\n this.#catalog = normalizeCatalog(catalog);\n this.#loadRuntime = loadRuntime;\n this.#pathCatalog = normalizePathCatalog(pathCatalog);\n\n for (const [id, loader] of this.#catalog) {\n assertFormId(id);\n if (typeof loader !== 'function') {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_ARGUMENT,\n `Form catalog loader \"${id}\" must be a function`,\n );\n }\n }\n for (const [path, loader] of this.#pathCatalog) {\n if (typeof loader !== 'function') {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_ARGUMENT,\n `Form path loader \"${path}\" must be a function`,\n );\n }\n }\n }\n\n deleteForm(id) {\n const formId = assertFormId(id);\n this.#loadedSources.delete(formId);\n this.#stores.delete(formId);\n const deletedForm = this.#forms.delete(formId);\n const deletedPath = this.#pathRegistrations.delete(formId);\n return deletedForm || deletedPath;\n }\n\n getFormIds() {\n return Object.freeze([...new Set([\n ...this.#catalog.keys(),\n ...this.#forms.keys(),\n ...this.#pathRegistrations.keys(),\n ])].sort());\n }\n\n getStore(id) {\n const store = this.#stores.get(assertFormId(id));\n return store ? Object.freeze({ ...store }) : null;\n }\n\n hasForm(id) {\n const formId = assertFormId(id);\n return this.#forms.has(formId)\n || this.#catalog.has(formId)\n || this.#pathRegistrations.has(formId);\n }\n\n loadForm(id) {\n return this.#loadSource(assertFormId(id));\n }\n\n async loadFormByPath(id, path) {\n const formId = assertFormId(id);\n const formPath = normalizeFormPath(path);\n const registeredPath = this.#pathRegistrations.get(formId);\n\n if (registeredPath && registeredPath !== formPath) {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.FORM_REGISTRATION_EXISTS,\n `Form \"${formId}\" is already registered from another path`,\n { id: formId, path: registeredPath },\n );\n }\n if (\n !registeredPath\n && (this.#catalog.has(formId) || this.#forms.has(formId))\n ) {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.FORM_REGISTRATION_EXISTS,\n `Form \"${formId}\" is already registered`,\n { id: formId },\n );\n }\n if (!this.#pathCatalog.has(formPath)) {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.FORM_PATH_NOT_FOUND,\n `Form path \"${formPath}\" is not available in the build catalog`,\n { id: formId, path: formPath },\n );\n }\n\n this.#pathRegistrations.set(formId, formPath);\n return this.#loadSource(formId);\n }\n\n async open(id, input = {}, options = {}) {\n const instance = await this.preload(id, input, options);\n const target = instance.mountTarget;\n if (target !== null && target !== undefined) await instance.mount(target);\n return instance;\n }\n\n async preload(id, input = {}, options = {}) {\n const formId = assertFormId(id);\n assertObject(options, 'preload options');\n assertNoDataUpdate(options, message => formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_ARGUMENT,\n message,\n ));\n\n const [mountRuntime, source] = await Promise.all([\n this.whenReady(),\n this.loadForm(formId),\n ]);\n const definition = await (typeof source === 'function'\n ? source(input, { id: formId, manager: this })\n : source);\n const store = {\n ...this.#stores.get(formId),\n ...options,\n };
1\n const runtime = normalizeRuntime(formId, definition, store);\n this.#sequence += 1;\n\n return new FormInstance({\n id: formId,\n instanceId: `form-instance-${this.#sequence}`,\n manager: this,\n mountRuntime,\n runtime,\n });\n }\n\n setForm(id, schemeOrFactory) {\n const formId = assertFormId(id);\n this.#forms.set(formId, assertSource(schemeOrFactory));\n this.#loadedSources.delete(formId);\n return this;\n }\n\n setStore(id, patch) {\n const formId = assertFormId(id);\n assertObject(patch, 'store patch');\n assertNoDataUpdate(patch, message => formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_ARGUMENT,\n message,\n ));\n this.#stores.set(formId, {\n ...this.#stores.get(formId),\n ...patch,\n });\n return this;\n }\n\n whenReady() {\n if (this.#runtimeReady) return this.#runtimeReady;\n\n this.#runtimeReady = Promise\n .resolve()\n .then(_ => this.#loadRuntime())\n .then(runtime => {\n if (!runtime || typeof runtime.mount !== 'function') {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_FORM_RUNTIME,\n 'FormManager runtime must provide mount(instance, target)',\n );\n }\n return runtime;\n })\n .catch(error => {\n this.#runtimeReady = null;\n throw error;\n });\n\n return this.#runtimeReady;\n }\n\n #loadSource(id) {\n if (this.#forms.has(id)) return Promise.resolve(this.#forms.get(id));\n if (this.#loadedSources.has(id)) return this.#loadedSources.get(id);\n\n const registeredPath = this.#pathRegistrations.get(id);\n const loader = registeredPath\n ? this.#pathCatalog.get(registeredPath)\n : this.#catalog.get(id);\n if (!loader) {\n return Promise.reject(formManagerError(\n FORM_MANAGER_ERROR_CODES.FORM_NOT_FOUND,\n `Form \"${id}\" is not registered`,\n { id },\n ));\n }\n\n const request = Promise\n .resolve()\n .then(_ => loader())\n .then(unwrapLoadedSource)\n .then(assertSource)\n .catch(error => {\n this.#loadedSources.delete(id);\n throw error;\n });\n this.#loadedSources.set(id, request);\n return request;\n }\n}\n\nexport default FormManager;\n"}),Object.freeze({label:"Project wiring и lazy catalog",source:"// classes\nimport { FormManager as BaseFormManager } from '@classes/FormManager/index.js';\n\n// plugins: form-generator\nimport { Form } from '@plugins/vue3-form-generator/src/data/index.js';\n\nimport {\n projectFormCatalog,\n projectFormPathCatalog,\n} from './catalog.js';\n\n\nexport const createProjectFormManager = ({\n configureHostApp,\n documentTarget,\n modalManager,\n}) => {\n const manager = new BaseFormManager({\n catalog: projectFormCatalog,\n loadRuntime: async _ => {\n const { createProjectFormRuntime } = await import('./runtime.js');\n return createProjectFormRuntime({\n configureHostApp,\n documentTarget,\n modalManager,\n });\n },\n pathCatalog: projectFormPathCatalog,\n });\n\n Object.defineProperty(manager, 'Form', {\n enumerable: true,\n value: Form,\n });\n\n return manager;\n};\n\nexport default createProjectFormManager;\n"}),Object.freeze({label:"ÐкземплÑÑ Ð¿Ð¾Ð´Ð³Ð¾Ñовленной ÑоÑмÑ",source:"import {\n FORM_MANAGER_ERROR_CODES,\n formManagerError,\n} from './FormManagerError.js';\n\n\nconst createDeferred = _ => {\n let resolve;\n const promise = new Promise(settle => { resolve = settle; });\n return { promise, resolve };\n};\n\nconst isPromiseLike = value => value && typeof value.then === 'function';\n\nexport class FormInstance {\n #closed = null;\n #closePromise = null;\n #handle = null;\n #manager = null;\n #mountRuntime = null;\n #resolveClosed = null;\n #runtime = null;\n #settled = false;\n #status = 'prepared';\n #target = null;\n\n constructor({ id, instanceId, manager, mountRuntime, runtime }) {\n const deferred = createDeferred();\n this.id = id;\n this.instanceId = instanceId;\n this.#closed = deferred.promise;\n this.#manager = manager;\n this.#mountRuntime = mountRuntime;
1\n this.#resolveClosed = deferred.resolve;\n this.#runtime = runtime;\n }\n\n get closed() {\n return this.#closed;\n }\n\n get dataForm() {\n return this.#runtime.dataForm;\n }\n\n get mountResult() {\n return this.#handle?.value ?? null;\n }\n\n get mountTarget() {\n return this.#runtime.mount;\n }\n\n get status() {\n return this.#status;\n }\n\n get target() {\n return this.#target;\n }\n\n close(result) {\n if (this.#settled) return Promise.resolve(false);\n if (this.#closePromise) return this.#closePromise;\n\n this.#closePromise = this.#performClose(result)\n .finally(_ => { this.#closePromise = null; });\n return this.#closePromise;\n }\n\n async #performClose(result) {\n if (this.#settled) return false;\n\n const handle = this.#handle;\n if (!handle) {\n this.#finish({ reason: 'programmatic', result });\n return true;\n }\n\n this.#status = 'closing';\n try {\n const isClosed = handle.close\n ? await handle.close(result)\n : (handle.unmount?.(), true);\n if (isClosed === false) {\n this.#status = 'open';\n return false;\n }\n this.#finish({ reason: 'programmatic', result });\n return true;\n } catch (error) {\n this.#status = 'open';\n throw error;\n }\n }\n\n async mount(target = this.mountTarget) {\n if (this.#settled) {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.FORM_INSTANCE_CLOSED,\n `Form \"${this.id}\" instance is closed`,\n { id: this.id },\n );\n }\n if (this.#handle || this.#status === 'mounting') {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.FORM_INSTANCE_MOUNTED,\n `Form \"${this.id}\" instance is already mounted`,\n { id: this.id },\n );\n }\n\n this.#status = 'mounting';\n try {\n const resolvedTarget = typeof target === 'function'\n ? await target({ id: this.id, instance: this, manager: this.#manager })\n : target;\n if (!resolvedTarget) {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_MOUNT_TARGET,\n `Form \"${this.id}\" requires a mount target`,\n { id: this.id },\n );\n }\n\n const handle = await this.#mountRuntime.mount(this, resolvedTarget);\n if (!handle || typeof handle !== 'object') {\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_FORM_RUNTIME,\n 'FormManager mount runtime must return a handle object',\n { id: this.id },\n );\n }\n if (this.#settled) {\n if (handle.close) await handle.close();\n else handle.unmount?.();\n throw formManagerError(\n FORM_MANAGER_ERROR_CODES.FORM_INSTANCE_CLOSED,\n `Form \"${this.id}\" instance was closed during mount`,\n { id: this.id },\n );\n }\n this.#handle = handle;\n this.#target = resolvedTarget;\n this.#status = 'open';\n\n if (this.#runtime.onMount) {\n await this.#runtime.onMount({\n id: this.id,\n instance: this,\n mountResult: this.mountResult,\n target: resolvedTarget,\n });\n }\n if (isPromiseLike(handle.closed)) {\n handle.closed.then(\n outcome => this.#finish(outcome),\n error => this.#finish({ error, reason: 'error' }),\n );\n }\n return this;\n } catch (error) {\n const handle = this.#handle;\n this.#handle = null;\n this.#target = null;\n this.#status = this.#settled ? 'closed' : 'prepared';\n try {\n if (handle?.close) await handle.close();\n else handle?.unmount?.();\n } catch (cleanupError) {\n void cleanupError;\n }\n throw error;\n }\n }\n\n getRuntime() {\n return this.#runtime;\n }\n\n #finish(outcome = {}) {\n if (this.#settled) return false;\n this.#settled = true;\n this.#status = 'closed';\n this.#resolveClosed(outcome);\n return true;\n }\n}\n\nexport default FormInstance;\n"}
1),Object.freeze({label:"DOM/ModalManagerV2 mount runtime",source:"// dependencies: vue\nimport { createApp } from 'vue';\n\n// classes\nimport {\n FORM_MANAGER_ERROR_CODES,\n formManagerError,\n} from '@classes/FormManager/FormManagerError.js';\n\n// components\nimport FormRuntime from '@cmp/FormManager/FormRuntime.vue';\n\n\nconst installedApps = new WeakMap();\n\nconst installFormGenerator = app => {\n if (installedApps.has(app)) return installedApps.get(app);\n\n const installation = Promise.all([\n import('@/helpers/FormGeneratorPlugin.js'),\n import('vue-select'),\n import('vue-imask'),\n ]).then(([FormGenerator, vSelect, Mask]) => {\n app.use(FormGenerator.default);\n app.component('v-select', vSelect.default);\n app.component('imask-input', Mask.IMaskComponent);\n\n const formStore = app.config.globalProperties.$store;\n if (!formStore?.commit) {\n throw new TypeError('FormGenerator store is not available');\n }\n return formStore;\n }).catch(error => {\n installedApps.delete(app);\n throw error;\n });\n\n installedApps.set(app, installation);\n return installation;\n};\n\nconst createDestroyForm = getStore => ({ formId }) => {\n const formStore = getStore();\n return formStore\n ? formStore.commit('FormGenerator/destroyForm', { formId })\n : false;\n};\n\nconst runtimeProps = (instance, destroyForm) => {\n const runtime = instance.getRuntime();\n return {\n dataForm: runtime.dataForm,\n destroyForm,\n fireContext: runtime.fireContext,\n functions: runtime.functions,\n onSubmit: runtime.onSubmit,\n onTrigger: runtime.onTrigger,\n updateData: runtime.updateData,\n };\n};\n\nconst isElement = value => value?.nodeType === 1;\n\nconst invalidTarget = (instance, message) => formManagerError(\n FORM_MANAGER_ERROR_CODES.INVALID_MOUNT_TARGET,\n `Form \"${instance.id}\" ${message}`,\n { id: instance.id },\n);\n\nexport const createProjectFormRuntime = ({\n configureHostApp,\n documentTarget,\n modalManager,\n}) => ({\n async mount(instance, target) {\n if (target === modalManager) {\n let formStore = null;\n formStore = await configureHostApp(installFormGenerator);\n\n const runtime = instance.getRuntime();\n let modalInstance = null;\n try {\n modalInstance = await modalManager.prepare('ModalForm', runtimeProps(\n instance,\n createDestroyForm(_ => formStore),\n ));\n modalInstance.setText('title', runtime.title);\n if (Object.keys(runtime.presentation).length) {\n modalInstance.setPresentation(runtime.presentation);\n }\n await modalManager.open(modalInstance);\n } catch (error) {\n if (modalInstance && modalInstance.status !== 'closed') {\n try {\n await modalInstance.close();\n } catch (cleanupError) {\n void cleanupError;\n }\n }\n throw error;\n }\n\n return {\n close: result => modalInstance.close(result),\n closed: modalInstance.closed,\n value: modalInstance,\n };\n }\n\n let element = target;\n if (typeof target === 'string') {\n try {\n element = documentTarget?.querySelector(target);\n } catch (selectorError) {\n void selectorError;\n throw invalidTarget(instance, `received invalid selector \"${target}\"`);\n }\n }\n if (!isElement(element)) {\n throw invalidTarget(\n instance,\n 'mount target must be a DOM element, selector or ModalManagerV2',\n );\n }\n\n const mountElement = element.ownerDocument.createElement('div');\n mountElement.dataset.formManagerInstance = instance.instanceId;\n element.append(mountElement);\n\n let app = null;\n let formStore = null;\n let mounted = null;\n try {\n app = createApp(FormRuntime, {\n ...runtimeProps(\n instance,\n createDestroyForm(_ => formStore),\n ),\n close: result => instance.close(result),\n });\n formStore = await installFormGenerator(app);
1\n mounted = app.mount(mountElement);\n } catch (error) {\n if (mounted) app.unmount();\n mountElement.remove();\n throw error;\n }\n\n let active = true;\n return {\n close() {\n if (!active) return false;\n active = false;\n app.unmount();\n mountElement.remove();\n return true;\n },\n value: mounted,\n };\n },\n});\n\nexport default createProjectFormRuntime;\n"}),Object.freeze({label:"ÐбÑий lifecycle FormGenerator",source:"<template>\n <div class=\"b-form-manager\">\n <p\n v-if=\"errorMessage\"\n :class=\"messageClass\"\n role=\"alert\">\n {{ errorMessage }}\n </p>\n <FormGenerator\n :data-form=\"dataForm\"\n :fire-context=\"fireContext\"\n :functions=\"functions\"\n :update-data=\"updateData\"\n @trigger=\"handleTrigger\" />\n </div>\n</template>\n\n<script>\nexport default { name: 'FormManagerRuntime' };\n<\/script>\n\n<script setup>\n// dependencies: vue\nimport {\n onBeforeUnmount,\n ref,\n} from 'vue';\n\n// classes\nimport { isModalFlowOutcome } from '@classes/ModalManager/modalFlow.js';\n\n\n//================================= props\nconst props = defineProps({\n close: { type: Function, required: true },\n dataForm: { type: Object, required: true },\n destroyForm: { type: Function, default: null },\n fireContext: { type: Boolean, default: false },\n functions: { type: Object, default: _ => ({}) },\n messageClass: { type: [Array, Object, String], default: null },\n onSubmit: { type: Function, default: null },\n onTrigger: { type: Function, default: null },\n updateData: { type: Object, default: null },\n});\n\n\n//================================= data\nconst errorMessage = ref('');\nlet formContext = null;\n\n\n//================================= methods\nconst releaseBusy = payload => {\n const { FormGenerator, formId } = payload ?? {};\n if (!FormGenerator?.setParams || !formId) return false;\n FormGenerator.setParams({ formId, isBusy: false });\n return true;\n};\n\nconst destroyForm = _ => {\n const context = formContext;\n formContext = null;\n const formId = context?.formId ?? props.dataForm?.params?.id;\n if (!formId) return false;\n\n if (props.destroyForm) {\n Promise.resolve(props.destroyForm({ formId })).catch(_ => false);\n return true;\n }\n if (!context?.api?.destroyForm) return false;\n context.api.destroyForm({ formId });\n return true;\n};\n\nconst handleTrigger = async payload => {\n if (payload?.FormGenerator) {\n formContext = {\n api: payload.FormGenerator,\n formId: payload.formId ?? payload.FormGenerator.formId,\n };\n }\n errorMessage.value = '';\n\n try {\n if (props.onTrigger) await props.onTrigger(payload);\n if (!['send', 'trigger'].includes(payload?.button?.type)) return;\n\n const outcome = props.onSubmit\n ? await props.onSubmit(payload)\n : payload?.sendData?.data ?? null;\n\n if (isModalFlowOutcome(outcome) && outcome.type === 'stay') {\n releaseBusy(payload);\n return;\n }\n if (isModalFlowOutcome(outcome) && outcome.type !== 'close') {\n throw new TypeError(`Unsupported form submit outcome: ${outcome.type}`);\n }\n\n const result = isModalFlowOutcome(outcome)\n ? outcome.result\n : outcome;\n const isClosed = await props.close(result);\n if (isClosed === false) releaseBusy(payload);\n } catch (error) {\n errorMessage.value = error?.message ?? String(error);\n releaseBusy(payload);\n }\n};\n\n\n//================================= lifecycle\nonBeforeUnmount(destroyForm);\n<\/script>\n\n<style lang=\"less\">\n@import '@less/variables/variables.less';\n\n.b-form-manager {\n min-width: 0;\n\n .b-modal-v2--sheet & > .form-generator {\n padding: 0;\n }\n\n & .input-control_checkbox &__agreement {\n color: @clr-ui-text;\n font-size: 0.7rem;\n line-height: 1.4285;\n }\n}\n</style>\n"}),Object.freeze({label:"УнивеÑÑалÑÐ½Ð°Ñ Ð¾Ð±Ð¾Ð»Ð¾Ñка ModalForm",source:Je}),Object.freeze({label:"Factory ÑоÑÐ¼Ñ ÑаÑÑÑлки",source:"import {\n Form,\n InputCheckbox,\n InputEmail,\n InputText,\n ListSearchableMulti,\n ParamsMaker,\n} from '@plugins/vue3-form-generator/src/';
1\n\nimport {\n agreementClasses,\n marketingConsent,\n personalDataConsent,\n} from './content.js';\n\n\nlet sequence = 0;\n\nconst topics = Object.freeze([\n Object.freeze({ id: 'all', label: 'ÐÑе' }),\n Object.freeze({ id: 'webinars', label: 'ÐебинаÑÑ' }),\n Object.freeze({ id: 'company-news', label: 'ÐовоÑÑи компании' }),\n Object.freeze({ id: 'support', label: 'ÐоддеÑжка' }),\n]);\n\nexport function createNewsletterSubscriptionRuntime({ formId = null } = {}) {\n sequence += 1;\n const resolvedFormId = formId ?? `form-manager-newsletter-${sequence}`;\n const form = new Form({\n baseId: 'form-manager',\n key: `newsletter-${sequence}`,\n prefix: 'form-manager-field-',\n })\n .setParams({\n id: resolvedFormId,\n buttons: [ParamsMaker.genButton('send', 'ÐодпиÑаÑÑÑÑ')],\n footerText: '* â обÑзаÑелÑнÑе Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ñ',\n hasFieldset: false,\n hasGroups: false,\n hasSteps: false,\n })\n .addField(ListSearchableMulti, {\n name: 'themes',\n data: [\n 'ТемаÑика',\n [topics[0]],\n {\n clearable: false,\n multi: true,\n options: topics,\n searchable: false,\n },\n ],\n validation: [['required']],\n })\n .addField(InputText, {\n name: 'name',\n label: 'ÐмÑ',\n value: '',\n attributes: {\n autocomplete: 'name',\n placeholder: 'Ðван',\n },\n })\n .addField(InputEmail, {\n name: 'email',\n label: 'E-mail',\n value: '',\n attributes: {\n autocomplete: 'email',\n placeholder: '[email protected]',\n },\n validation: [['required'], ['email']],\n })\n .addField(InputText, {\n name: 'company',\n label: 'ÐомпаниÑ',\n value: '',\n attributes: {\n autocomplete: 'organization',\n placeholder: 'ÐÐР«Телеком»',\n },\n validation: [['required']],\n })\n .addField(InputText, {\n name: 'position',\n label: 'ÐолжноÑÑÑ',\n value: '',\n attributes: {\n autocomplete: 'organization-title',\n placeholder: 'ÐенеджеÑ',\n },\n })\n .addField(InputCheckbox, {\n name: 'personal-data-consent',\n label: personalDataConsent('ÐодпиÑаÑÑÑÑ'),\n value: false,\n classes: agreementClasses,\n validation: [['required']],\n })\n .addField(InputCheckbox, {\n name: 'marketing-consent',\n label: marketingConsent,\n value: false,\n classes: agreementClasses,\n })\n .setup()\n .setReady();\n\n const { form: dataForm, functions } = form;\n return {\n dataForm,\n functions,\n title: 'ÐодпиÑаÑÑÑÑ Ð½Ð° ÑаÑÑÑлкÑ',\n };\n}\n\nexport default createNewsletterSubscriptionRuntime;\n"})]),Ze=Object.freeze({description:"ÐеÑÑÑ Ð¿ÑедопÑеделÑннÑÑ ÑоÑÐ¼Ñ ÑаÑÑÑлки из lazy catalog FormManager и оÑкÑÑÐ²Ð°ÐµÑ ÐµÑ ÑеÑез ÑнивеÑÑалÑнÑй ModalForm в presentation dialog-lg. Submit не обÑаÑаеÑÑÑ Ðº backend: payload возвÑаÑаеÑÑÑ ÐºÐ°Ðº result закÑÑÑого FormInstance.",expected:["Ð ÑиÑоком диалоге оÑобÑажаеÑÑÑ FormGenerator Ñ ÑемаÑиками, конÑакÑнÑми полÑми и ÑоглаÑиÑми ÑоÑÐ¼Ñ ÑаÑÑÑлки.","Ðнопка «ÐодпиÑаÑÑÑÑ» иÑполÑзÑÐµÑ client validation и busy lifecycle FormGenerator.","ÐоÑле submit окно закÑÑваеÑÑÑ, а жÑÑнал показÑÐ²Ð°ÐµÑ JSON-ÑовмеÑÑимÑй form payload без ÑеÑевого запÑоÑа.","Reset закÑÑÐ²Ð°ÐµÑ ÑолÑко пÑинадлежаÑий кейÑÑ FormInstance и ÑниÑÑÐ¾Ð¶Ð°ÐµÑ form store."],group:"ÐÑоизволÑное ÑодеÑжимое",id:"MMV2-X04",safety:"read-only",tags:["FormGenerator","FormManager","ModalForm","dialog-lg"],title:"ÐÑкÑÑÑÑ ÑоÑÐ¼Ñ ÑаÑÑÑлки в dialog-lg",useWhen:"Ðогда длинной ÑоÑме нÑжен ÑиÑокий диалог, а consumer должен вÑзваÑÑ ÐµÑ Ð¿Ð¾ ÑÑабилÑÐ½Ð¾Ð¼Ñ ID без ÑÑÑной ÑбоÑки ModalInstance и Vuex lifecycle.",warnings:["ModalForm â ÑнивеÑÑалÑнÑй modal adapter Ð´Ð»Ñ FormGenerator, а не оÑделÑнÑй renderer ÑоÑмÑ.","Factory ÑоздаÑÑ Ð½Ð¾Ð²Ñй dataForm Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ оÑкÑÑÑиÑ;
1 mutable runtime Ð¼ÐµÐ¶Ð´Ñ ÑеÑÑиÑми не пеÑеиÑполÑзÑеÑÑÑ.","ÐÑÐ¸Ð¼ÐµÑ Ð½Ð°Ð¼ÐµÑенно не вÑзÑÐ²Ð°ÐµÑ production transport ÑоÑÐ¼Ñ ÑаÑÑÑлки."]}),Qe=Object.freeze(Object.defineProperty({__proto__:null,default:Ze,recipe:Ze,run:async({globalTarget:n,log:t,namespaceKey:a,own:r})=>{const o=n[a]?.FormManager,s=n[a]?.ModalManagerV2;if(!o)throw new Error("FormManager is not available");if(!s)throw new Error("ModalManagerV2 is not available");const i=r(await o.open(Ke,{},{mount:s,onSubmit:n=>{const a=n?.sendData?.data??null;return t("FormManager полÑÑил submit ÑоÑÐ¼Ñ ÑаÑÑÑлки",a),e.close(a)},presentation:{preset:"dialog-lg"}}));t("ФоÑма ÑаÑÑÑлки оÑкÑÑÑа ÑеÑез ModalForm",{formId:Ke,instanceId:i.instanceId,modalId:i.mountResult.id,preset:"dialog-lg"})},supportingSources:Ye},Symbol.toStringTag,{value:"Module"})),en="Footer/CallbackRequest",nn=Object.freeze([Object.freeze({label:"Factory ÑоÑÐ¼Ñ Ð¾Ð±ÑаÑного звонка",source:"import {\n Form,\n InputCheckbox,\n InputPhone,\n InputText,\n ParamsMaker,\n} from '@plugins/vue3-form-generator/src/';\n\nimport {\n agreementClasses,\n marketingConsent,\n personalDataConsent,\n} from './content.js';\n\n\nlet sequence = 0;\n\nexport function createCallbackRequestRuntime({ formId = null } = {}) {\n sequence += 1;\n const resolvedFormId = formId ?? `form-manager-callback-${sequence}`;\n const form = new Form({\n baseId: 'form-manager',\n key: `callback-${sequence}`,\n prefix: 'form-manager-field-',\n })\n .setParams({\n id: resolvedFormId,\n buttons: [ParamsMaker.genButton('send', 'ÐÑпÑавиÑÑ')],\n hasFieldset: false,\n hasGroups: false,\n hasSteps: false,\n undertitle: 'ÐÐ°Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ ÑвÑжеÑÑÑ Ñ Ð²Ð°Ð¼Ð¸ в ÑеÑение ÑабоÑего днÑ',\n })\n .addField(InputText, {\n name: 'name',\n label: 'ÐмÑ',\n value: '',\n attributes: {\n autocomplete: 'name',\n placeholder: 'ÐмÑ',\n },\n validation: [['required']],\n })\n .addField(InputPhone, {\n name: 'phone',\n label: 'ТелеÑон',\n value: '',\n attributes: {\n autocomplete: 'tel',\n placeholder: 'ТелеÑон',\n },\n validation: [['required'], ['phone']],\n })\n .addField(InputCheckbox, {\n name: 'personal-data-consent',\n label: personalDataConsent('ÐÑпÑавиÑÑ'),\n value: false,\n classes: agreementClasses,\n validation: [['required']],\n })\n .addField(InputCheckbox, {\n name: 'marketing-consent',\n label: marketingConsent,\n value: false,\n classes: agreementClasses,\n })\n .setup()\n .setReady();\n\n const { form: dataForm, functions } = form;\n return {\n dataForm,\n functions,\n title: 'ÐаказаÑÑ Ð¾Ð±ÑаÑнÑй звонок',\n };\n}\n\nexport default createCallbackRequestRuntime;\n"}),Object.freeze({label:"УнивеÑÑалÑÐ½Ð°Ñ Ð¾Ð±Ð¾Ð»Ð¾Ñка ModalForm",source:Je})]),tn=Object.freeze({description:"ÐÑкÑÑÐ²Ð°ÐµÑ Ð¿ÑедопÑеделÑннÑÑ ÑоÑÐ¼Ñ Ð¾Ð±ÑаÑного звонка ÑеÑез ÑÐ¾Ñ Ð¶Ðµ ModalForm, но менÑÐµÑ presentation на боковой sheet. Так ÑоÑма и ÐµÑ lifecycle оÑÑаÑÑÑÑ Ð¿Ñежними, а ÑпоÑоб показа задаÑÑ options ÑекÑÑего вÑзова FormManager.",expected:["СпÑава оÑкÑÑваеÑÑÑ sheet Ñ Ð¿Ð¾Ð»Ñми имени, ÑелеÑона и двÑÐ¼Ñ ÑоглаÑиÑми.","ФоÑма иÑполÑзÑÐµÑ ÑÑ Ð¶Ðµ universal ModalForm, ÑÑо и ÐºÐµÐ¹Ñ ÑаÑÑÑлки; оÑлиÑаеÑÑÑ ÑолÑко presentation.","Submit пÑоÑ
Ð¾Ð´Ð¸Ñ client validation, не вÑзÑÐ²Ð°ÐµÑ backend и закÑÑÐ²Ð°ÐµÑ FormInstance Ñ payload в result."],group:"ÐÑоизволÑное ÑодеÑжимое",id:"MMV2-X05",safety:"read-only",tags:["FormGenerator","FormManager","ModalForm","sheet"],title:"ÐÑкÑÑÑÑ ÑоÑÐ¼Ñ Ð·Ð²Ð¾Ð½ÐºÐ° в sheet",useWhen:"Ðогда компакÑнÑÑ ÑоÑÐ¼Ñ Ð½Ñжно показаÑÑ ÑÐ±Ð¾ÐºÑ Ð¸ ÑоÑ
ÑаниÑÑ ÐµÐ´Ð¸Ð½Ñй API open/closed незавиÑимо Ð¾Ñ presentation ModalManagerV2.",warnings:["Presentation не должен попадаÑÑ Ð²Ð½ÑÑÑÑ FormGenerator-ÑÑ
емÑ: его пÑименÑÐµÑ modal adapter FormManager.","ÐÑÐ¸Ð¼ÐµÑ Ð½Ð°Ð¼ÐµÑенно не вÑзÑÐ²Ð°ÐµÑ production transport ÑоÑÐ¼Ñ Ð¾Ð±ÑаÑного звонка."]}),an=Object.freeze(Object.defineProperty({__proto__:null,default:tn,recipe:tn,run:async({globalTarget:n,log:t,namespaceKey:a,own:r})=>{const o=n[a]?.FormManager,s=n[a]?.ModalManagerV2;if(!o)throw new Error("FormManager is not available");if(!s)throw new Error("ModalManagerV2 is not available");const i=r(await o.open(en,{},{mount:s,onSubmit:n=>{const a=n?.sendData?.data??null;return t("FormManager полÑÑил submit ÑоÑÐ¼Ñ Ð¾Ð±ÑаÑного звонка",a),e.close(a)},presentation:{preset:"sheet",side:"right"}}));t("ФоÑма обÑаÑного звонка оÑкÑÑÑа ÑеÑез ModalForm",{formId:en,instanceId:i.instanceId,modalId:i.mountResult.id,preset:"sheet"})},supportingSources:nn},Symbol.toStringTag,{value:"Module"})),rn=Object.freeze(["ÐодклÑÑение и API","СÑандаÑÑнÑе окна","ÐÑоизволÑное ÑодеÑжимое","ÐнеÑний вид","ÐизненнÑй Ñикл","ÐÑинÑ
ÑоннÑе дейÑÑвиÑ","СоÑÑоÑние и ÑобÑÑиÑ"]),on=Object.freeze({LOCAL_SIDE_EFFECT:"local-side-effect",READ_ONLY:"read-only"}),sn=Object.assign({"./mmv2-a01-async-action.js":$,"./mmv2-c01-error-retry.js":B,"./mmv2-c02-success.js":q,"./mmv2-c03-prompt.js":X,"./mmv2-c04-download.js":K,"./mmv2-c05-product-filters.js":ne,"./mmv2-l01-repeated-open.js":ae,"./mmv2-l02-stack.js":oe,"./mmv2-l03-replace.js":ie,"./mmv2-l04-timeout-close.js":ce,"./mmv2-o01-events-state.js":ue,"./mmv2-o02-store.js":pe,"./mmv2-p01-presentation.js":fe,"./mmv2-p02-dynamic.js":be,"./mmv2-p03-disabled-action.js":ve,"./mmv2-p04-anchored-panel.js":Oe,"./mmv2-p05-owned-panel.js":je,"./mmv2-p06-anchored-modal.js":Re,"./mmv2-r01-readiness.js":_e,"./mmv2-r02-prepare-open.js":Ae,"./mmv2-x01-html.js":Le,"./mmv2-x02-js-configurator.js":Ue,"./mmv2-x03-vue-component.js":Xe,"./mmv2-x04-form-generator.js":Qe,"./mmv2-x05-callback-form.js":an}),ln=Object.assign({"./mmv2-a01-async-action.js":"export const recipe = Object.freeze({\n description: 'ÐапÑÑÐºÐ°ÐµÑ Ð´ÐµÐ¹ÑÑвие длиÑелÑноÑÑÑÑ 1,5 ÑекÑндÑ, блокиÑÑÐµÑ ÐµÐ³Ð¾ повÑоÑнÑй запÑÑк и ÑÐ¼ÐµÐµÑ ÐºÐ¾ÑÑекÑно оÑменÑÑÑ ÑабоÑÑ Ð¿Ñи закÑÑÑии окна.',\n expected: [\n 'Ðока дейÑÑвие вÑполнÑеÑÑÑ, поле busyActionId ÑодеÑÐ¶Ð¸Ñ ID кнопки confirm, а кнопка недоÑÑÑпна Ð´Ð»Ñ Ð¿Ð¾Ð²ÑоÑного запÑÑка.',\n 'ÐовÑоÑнÑй вÑзов полÑÑÐ°ÐµÑ Ñже вÑполнÑÑÑÑÑÑÑ Ð¾Ð¿ÐµÑаÑÐ¸Ñ (single-flight), а не ÑоздаÑÑ Ð²ÑоÑÑÑ.',\n 'ÐакÑÑÑие окна или ÑбÑÐ¾Ñ ÐºÐµÐ¹Ñа оÑменÑÐµÑ AbortSignal, вÑполнÑÐµÑ Ð¾ÑиÑÑÐºÑ Ð¸ игноÑиÑÑÐµÑ Ð·Ð°Ð¿Ð¾Ð·Ð´Ð°Ð²Ñий ÑезÑлÑÑаÑ.',\n ],\n group: 'ÐÑинÑ
ÑоннÑе дейÑÑвиÑ',\n id: 'MMV2-A01',\n safety: 'read-only',\n tags: ['async', 'busy', 'abort'],\n title: 'ÐаблокиÑоваÑÑ Ð¿Ð¾Ð²ÑоÑнÑй запÑÑк дейÑÑвиÑ',\n useWhen: 'ÐÐ»Ñ Ð°ÑинÑ
Ñонной ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð²Ð½ÑÑÑи окна, коÑоÑÑÑ Ð½ÐµÐ»ÑÐ·Ñ Ð·Ð°Ð¿ÑÑкаÑÑ Ð´Ð²Ð°Ð¶Ð´Ñ Ð¸ коÑоÑÑÑ Ð½Ñжно оÑÑановиÑÑ, еÑли полÑзоваÑÐµÐ»Ñ Ð·Ð°ÐºÑÑл окно.',\n});\n\nexport const run = async ({ log, manager, own }) =>
1 {\n const instance = own(await manager.prepare('ModalPrompt', {\n details: 'ÐажмиÑе «ÐапÑÑÑиÑÑ 1,5 Ñ». Ðа вÑÐµÐ¼Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° ÑÑÐ°Ð½ÐµÑ Ð½ÐµÐ´Ð¾ÑÑÑпной, а busyActionId бÑÐ´ÐµÑ Ñавен confirm.',\n }));\n\n instance\n .setText('title', 'MMV2-A01: аÑинÑ
Ñонное дейÑÑвие')\n .setAction({\n closePolicy: 'never',\n id: 'confirm',\n role: 'primary',\n text: 'ÐапÑÑÑиÑÑ 1,5 Ñ',\n })\n .setActionHandler('confirm', async ({\n flow,\n instance: current,\n onCleanup,\n signal,\n }) => {\n log('ÐÑинÑ
Ñонное дейÑÑвие наÑаÑо', current.getState());\n\n const completed = await new Promise(resolve => {\n const timer = setTimeout(_ => resolve(true), 1500);\n const onAbort = _ => {\n clearTimeout(timer);\n resolve(false);\n };\n signal.addEventListener('abort', onAbort, { once: true });\n onCleanup(_ => {\n clearTimeout(timer);\n signal.removeEventListener('abort', onAbort);\n log('РеÑÑÑÑÑ Ð°ÑинÑ
Ñонного дейÑÑÐ²Ð¸Ñ Ð¾ÑиÑенÑ');\n });\n });\n\n if (!completed || signal.aborted) return flow.stay({ aborted: true });\n current.setProps({ details: 'ÐÑинÑ
Ñонное дейÑÑвие завеÑÑено; окно оÑÑалоÑÑ Ð¾ÑкÑÑÑÑм.' });\n log('ÐÑинÑ
Ñонное дейÑÑвие завеÑÑено', current.getState());\n return flow.stay({ completed: true });\n });\n\n await manager.open(instance);\n log('ModalPrompt гоÑов к аÑинÑ
ÑÐ¾Ð½Ð½Ð¾Ð¼Ñ Ð´ÐµÐ¹ÑÑвиÑ', instance.getState());\n};\n","./mmv2-c01-error-retry.js":"export const recipe = Object.freeze({\n description: 'ÐÑкÑÑÐ²Ð°ÐµÑ ÑÑандаÑÑное окно оÑибки ModalError и добавлÑÐµÑ ÐºÐ½Ð¾Ð¿ÐºÑ Ð¿Ð¾Ð²ÑоÑной попÑÑки, коÑоÑÐ°Ñ Ð½Ðµ закÑÑÐ²Ð°ÐµÑ Ð¾ÐºÐ½Ð¾.',\n expected: [\n 'СÑÑока, поÑ
Ð¾Ð¶Ð°Ñ Ð½Ð° HTML-код, вÑводиÑÑÑ Ð¾Ð±ÑÑнÑм ÑекÑÑом и не иÑполнÑеÑÑÑ Ð±ÑаÑзеÑом.',\n 'Ðаждое нажаÑие «ÐовÑоÑиÑÑ» ÑвелиÑÐ¸Ð²Ð°ÐµÑ ÑÑÑÑÑик, пÑинадлежаÑий ÑолÑко ÑÑÐ¾Ð¼Ñ ÑкземплÑÑÑ Ð¾ÐºÐ½Ð°.',\n 'РезÑлÑÑÐ°Ñ flow.stay оÑÑавлÑÐµÑ ÑÐ¾Ñ Ð¶Ðµ ÑкземплÑÑ Ð¾ÑкÑÑÑÑм поÑле обÑабоÑÑика.',\n ],\n group: 'СÑандаÑÑнÑе окна',\n id: 'MMV2-C01',\n safety: 'read-only',\n tags: ['ModalError', 'retry', 'stay'],\n title: 'ÐÑибка Ñ Ð¿Ð¾Ð²ÑоÑной попÑÑкой',\n useWhen: 'ÐÐ»Ñ Ð¸ÑпÑавимой оÑибки инÑеÑÑейÑа или API, поÑле коÑоÑой полÑзоваÑÐµÐ»Ñ Ð¼Ð¾Ð¶ÐµÑ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñно повÑоÑиÑÑ Ð¾Ð¿ÐµÑаÑиÑ.',\n});\n\nexport const run = async ({ log, manager, own }) => {\n const instance = own(await manager.prepare('ModalError', {\n details: `<script>${['al', 'ert'].join('')}(\"не вÑполниÑÑÑ\")<\/script>`,\n messages: ['ÐемонÑÑÑаÑÐ¸Ð¾Ð½Ð½Ð°Ñ Ð¾Ñибка. ÐаннÑе на ÑеÑвеÑе не изменÑÑÑÑÑ.'],\n }));\n\n instance\n .setText('title', 'MMV2-C01: оÑибка Ñ Ð¿Ð¾Ð²ÑоÑной попÑÑкой')\n .setStore('retryCount', 0)\n .setAction({\n closePolicy: 'never',\n id: 'retry',\n role: 'primary',\n text: 'ÐовÑоÑиÑÑ',\n })\n .setActionHandler('retry', ({ flow, instance: current }) => {\n const retryCount = (current.getStore('retryCount') ?? 0) + 1;\n current\n .setStore('retryCount', retryCount)\n .setProps({ messages: [`ÐопÑÑка ${retryCount} вÑполнена локалÑно.`] });\n log('ÐовÑоÑÐ½Ð°Ñ Ð¿Ð¾Ð¿ÑÑка завеÑÑена; окно оÑÑалоÑÑ Ð¾ÑкÑÑÑÑм', { retryCount });\n return flow.stay({ retryCount });\n });\n\n await manager.open(instance);\n log('ModalError оÑкÑÑÑ', instance.getState());\n};\n","./mmv2-c02-success.js":"export const recipe = Object.freeze({\n description: 'ÐÑкÑÑÐ²Ð°ÐµÑ ÑÑандаÑÑное окно ModalSuccess, ÑообÑÐ°ÐµÑ Ð¾Ð± ÑÑпеÑном завеÑÑении опеÑаÑии и пÑÐµÐ´Ð»Ð°Ð³Ð°ÐµÑ Ð·Ð°ÐºÑÑÑÑ Ñведомление.',\n expected: [\n 'ÐоÑоÑÐºÐ°Ñ ÑоÑма open пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ title и message; пеÑеданнÑй message заменÑÐµÑ default-ÑекÑÑ Ð¾ÐºÐ½Ð°.',\n 'ÐÑÑÑой message ÑкÑÑÐ²Ð°ÐµÑ default-ÑекÑÑ, а messages вÑÐ²Ð¾Ð´Ð¸Ñ Ð¾ÑделÑнÑе пÑнкÑÑ ÑпиÑка без default-ÑекÑÑа.',\n 'Ðнопка «ÐакÑÑÑÑ» иÑполÑзÑÐµÑ Ð²ÑÑÑоенное закÑÑÑие и не ÑÑебÑÐµÑ Ð¾ÑделÑного обÑабоÑÑика.',\n 'Promise instance.closed ÑообÑÐ°ÐµÑ Ð¿ÑиÑÐ¸Ð½Ñ Ð·Ð°ÐºÑÑÑÐ¸Ñ (reason) и пеÑеданнÑй ÑезÑлÑÑÐ°Ñ (result).',\n ],\n group: 'СÑандаÑÑнÑе окна',\n id: 'MMV2-C02',\n safety: 'read-only',\n tags: ['ModalSuccess', 'close', 'result'],\n title: 'СообÑиÑÑ Ð¾Ð± ÑÑпеÑном завеÑÑении',\n useWhen: 'ÐоÑле оконÑаÑелÑно завеÑÑÑнной опеÑаÑии, когда полÑзоваÑÐµÐ»Ñ Ð½Ñжно показаÑÑ ÑезÑлÑÑÐ°Ñ Ð¸ вÑвеÑÑи его из ÑекÑÑего ÑаÐ
1³Ð°.',\n});\n\nexport const run = async ({ log, manager, own }) => {\n const instance = own(await manager.open('ModalSuccess', {\n message: 'ÐпеÑаÑÐ¸Ñ Ð·Ð°Ð²ÐµÑÑена в демонÑÑÑаÑионном Ñежиме.',\n title: 'MMV2-C02: опеÑаÑÐ¸Ñ Ð·Ð°Ð²ÐµÑÑена',\n }));\n\n log('ModalSuccess оÑкÑÑÑ Ñо вÑÑÑоеннÑм дейÑÑвием закÑÑÑиÑ', instance.getState());\n};\n","./mmv2-c03-prompt.js":"export const recipe = Object.freeze({\n description: 'ÐÑкÑÑÐ²Ð°ÐµÑ Ð¾ÐºÐ½Ð¾ подÑвеÑÐ¶Ð´ÐµÐ½Ð¸Ñ ModalPrompt и оÑделÑÐµÑ Ñвное ÑоглаÑие Ð¾Ñ Ð»Ñбого ÑпоÑоба оÑÐ¼ÐµÐ½Ñ Ð¸Ð»Ð¸ закÑÑÑиÑ.',\n expected: [\n 'ТолÑко кнопка подÑвеÑÐ¶Ð´ÐµÐ½Ð¸Ñ ÑвелиÑÐ¸Ð²Ð°ÐµÑ ÑÑÑÑÑик вÑполненнÑÑ
команд businessActionCount.',\n 'ÐÑмена, Escape, кнопка закÑÑÑÐ¸Ñ Ð¸ клик по ÑÐ¾Ð½Ñ Ð·Ð°ÐºÑÑваÑÑ Ð¾ÐºÐ½Ð¾ без вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ.',\n 'ÐовÑоÑное подÑвеÑждение во вÑÐµÐ¼Ñ Ñже запÑÑенного дейÑÑÐ²Ð¸Ñ Ð½Ðµ ÑоздаÑÑ Ð²ÑоÑÑÑ Ð¾Ð¿ÐµÑаÑиÑ.',\n ],\n group: 'СÑандаÑÑнÑе окна',\n id: 'MMV2-C03',\n safety: 'read-only',\n tags: ['ModalPrompt', 'confirm', 'dismiss'],\n title: 'ÐапÑоÑиÑÑ Ð¿Ð¾Ð´ÑвеÑждение дейÑÑвиÑ',\n useWhen: 'ÐеÑед командой, коÑоÑÑÑ ÑазÑеÑено вÑполнÑÑÑ ÑолÑко поÑле Ñвного ÑоглаÑÐ¸Ñ Ð¿Ð¾Ð»ÑзоваÑелÑ, но не пÑи закÑÑÑии окна.',\n});\n\nexport const run = async ({ log, manager, own }) => {\n const instance = own(await manager.prepare('ModalPrompt', {\n details: 'ÐодÑвеÑдиÑе локалÑнÑÑ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑаÑионнÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ.',\n }));\n\n instance\n .setText('title', 'MMV2-C03: подÑвеÑдиÑе дейÑÑвие')\n .setPresentation({ dismiss: { backdrop: true } })\n .setStore('businessActionCount', 0)\n .setActionHandler('confirm', ({ flow, instance: current }) => {\n const businessActionCount = (\n current.getStore('businessActionCount') ?? 0\n ) + 1;\n current.setStore('businessActionCount', businessActionCount);\n log('Ðоманда вÑполнена поÑле Ñвного подÑвеÑждениÑ', { businessActionCount });\n return flow.close({ businessActionCount, confirmed: true });\n });\n\n await manager.open(instance);\n log('ModalPrompt Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ ÑеÑениÑ', instance.getState());\n};\n","./mmv2-c04-download.js":"export const recipe = Object.freeze({\n description: 'СоздаÑÑ Ð½ÐµÐ±Ð¾Ð»ÑÑой ÑекÑÑовÑй Ñайл пÑÑмо в бÑаÑзеÑе и показÑÐ²Ð°ÐµÑ ÑÑандаÑÑное окно загÑÑзки ModalDownload.',\n expected: [\n 'Файл не загÑÑжаеÑÑÑ Ð°Ð²ÑомаÑиÑеÑки: полÑзоваÑÐµÐ»Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ Ñвно нажаÑÑ ÐºÐ½Ð¾Ð¿ÐºÑ Ð·Ð°Ð³ÑÑзки.',\n 'Ðкно полÑÑÐ°ÐµÑ Ð²ÑеменнÑй адÑÐµÑ blob:, ÑозданнÑй бÑаÑзеÑом, поÑÑÐ¾Ð¼Ñ Ð·Ð°Ð¿ÑÐ¾Ñ Ðº API не вÑполнÑеÑÑÑ.',\n 'ÐÑи закÑÑÑии окна или ÑбÑоÑе кейÑа вÑеменнÑй Object URL оÑвобождаеÑÑÑ.',\n ],\n group: 'СÑандаÑÑнÑе окна',\n id: 'MMV2-C04',\n safety: 'local-side-effect',\n tags: ['ModalDownload', 'Blob', 'cleanup'],\n title: 'ÐоказаÑÑ Ð·Ð°Ð³ÑÑÐ·ÐºÑ Ð»Ð¾ÐºÐ°Ð»Ñного Ñайла',\n useWhen: 'ÐÐ»Ñ Ð¿ÑовеÑки инÑеÑÑейÑа загÑÑзки без обÑаÑÐµÐ½Ð¸Ñ Ðº API и без Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ
на ÑеÑвеÑе.',\n});\n\nexport const run = async ({\n createLocalObjectUrl,\n globalTarget,\n log,\n manager,\n own,\n}) => {\n const blob = new globalTarget.Blob(\n ['ModalManagerV2 local recipe\\n'],\n { type: 'text/plain;charset=utf-8' },\n );\n const { revoke, url } = createLocalObjectUrl(blob);\n const instance = own(await manager.prepare('ModalDownload', {\n autoClose: false,\n autoStart: false,\n countdown: 0,\n filename: 'modal-manager-v2-recipe.txt',\n url,\n }));\n\n instance\n .setText('title', 'MMV2-C04: локалÑнÑй Ñайл')\n .onDispose(revoke);\n\n await manager.open(instance);\n log('ModalDownload оÑкÑÑÑ Ñ Ð»Ð¾ÐºÐ°Ð»ÑнÑм Blob URL', {\n filename: 'modal-manager-v2-recipe.txt',\n protocol: new globalTarget.URL(url).protocol,\n });\n};\n","./mmv2-c05-product-filters.js":"// classes\nimport { modalFlow } from '@classes/ModalManager/index.js';\n\n// resources\nimport formSource from '@/modules/form-manager/forms/product-filters.js?raw';\nimport integrationSource from './product-filter-frontend-integration.js?raw';\n\n\nconst FORM_ID = 'Catalog/ProductFilters';\nconst frontendTriggerSource = `<div data-product-filter-trigger>\n @php\n echo \\\\Infotecs\\\\UiRenderer\\\\UiRenderer::render('/common/chip/chip', [\n 'id' => 'product-filters-trigger',\n 'name' => 'ФилÑÑÑÑ',\n ], false);\n @endphp\n</div>`;
1\n\nexport const supportingSources = Object.freeze([\n Object.freeze({ label: 'ФабÑика ÑоÑÐ¼Ñ Ð² lazy-каÑалоге', source: formSource }),\n Object.freeze({ label: 'РазмеÑка ÑÑиггеÑа во frontend Blade', source: frontendTriggerSource }),\n Object.freeze({ label: 'ÐодклÑÑение из оÑделÑного frontend bundle', source: integrationSource }),\n]);\n\nexport const readProductFilters = result => {\n const fields = Array.isArray(result?.fields) ? result.fields : [];\n const query = String(fields.find(field => field.name === 'query')?.model ?? '');\n const selected = Object.fromEntries(fields\n .filter(field => field.name !== 'query' && Array.isArray(field.model))\n .map(field => [field.name, [...field.model]]));\n const count = (query.trim() ? 1 : 0)\n + Object.values(selected).reduce((total, values) => total + values.length, 0);\n\n return { query, selected, count };\n};\n\nexport const recipe = Object.freeze({\n description: 'UIChip оÑкÑÑÐ²Ð°ÐµÑ Ð±Ð¾ÐºÐ¾Ð²ÑÑ ÑÑоÑÐºÑ Ñ FormGenerator-ÑилÑÑÑом: одно поле обÑего поиÑка и неÑколÑко гÑÑпп ChipAccordion без внÑÑÑеннего поиÑка. ФоÑма пÑÐ¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ lazy-каÑÐ°Ð»Ð¾Ð³Ñ frontend-cabinet, а поÑÑебиÑÐµÐ»Ñ Ð¿ÐµÑедаÑÑ Ð³ÑÑÐ¿Ð¿Ñ Ð¸ полÑÑÐ°ÐµÑ ÑезÑлÑÑÐ°Ñ ÑеÑез FormManager.',\n expected: [\n 'ÐажаÑие на Ñип «ФилÑÑÑÑ» оÑкÑÑÐ²Ð°ÐµÑ ÑпÑава ÑÑоÑÐºÑ Ñ Ð¿Ð¾Ð¸Ñком и ÑÑÐµÐ¼Ñ Ð³ÑÑппами ваÑианÑов.',\n 'Ркаждой гÑÑппе Ð²Ð¸Ð´Ð½Ñ Ð¿ÐµÑвÑе ÑÑи ваÑианÑа, оÑÑалÑнÑе ÑаÑкÑÑваÑÑÑÑ; оÑделÑного поиÑка внÑÑÑи ChipAccordion неÑ.',\n '«ÐоказаÑÑ» закÑÑÐ²Ð°ÐµÑ ÑоÑмÑ: ÑиÑÑа на Ñипе Ñавна ÑиÑÐ»Ñ Ð²ÑбÑаннÑÑ
ваÑианÑов плÑÑ Ð¾Ð´Ð¸Ð½ за непÑÑÑой поиÑковÑй запÑоÑ.',\n 'ÐовÑоÑное оÑкÑÑÑие ÑоздаÑÑ Ð½Ð¾Ð²Ñй FormInstance Ñ ÑоÑ
ÑанÑннÑми кÑиÑеÑиÑми; ÑбÑÐ¾Ñ ÐºÐµÐ¹Ñа закÑÑÐ²Ð°ÐµÑ ÑÑоÑÐºÑ Ð¸ оÑиÑÐ°ÐµÑ Ñип.',\n ],\n group: 'СÑандаÑÑнÑе окна',\n id: 'MMV2-C05',\n safety: 'read-only',\n tags: ['UIChip', 'ChipAccordion', 'FormManager', 'sheet'],\n title: 'ФилÑÑÑ Ð¿ÑодÑкÑов в ÑÑоÑке',\n trigger: 'chip',\n useWhen: 'Ðогда оÑделÑнÑй frontend-ÑкÑÐ¸Ð¿Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ оÑкÑÑÑÑ ÑоÑмÑ-ÑилÑÑÑ Ð¿Ð¾ ÑÑабилÑÐ½Ð¾Ð¼Ñ ID поÑле гоÑовноÑÑи ÑеÑвиÑов, не импоÑÑиÑÑÑ Vue и адапÑеÑÑ FormGenerator.',\n warnings: [\n 'ÐемонÑÑÑаÑионнÑе ваÑианÑÑ Ð½Ðµ ÑвлÑÑÑÑÑ Ð°ÐºÑÑалÑнÑм каÑалогом пÑодÑкÑов; ÑеалÑнÑе гÑÑÐ¿Ð¿Ñ Ð¸ обÑабоÑÐºÑ ÑезÑлÑÑаÑа задаÑÑ Ð²ÑзÑваÑÑий код.',\n 'ÐоиÑк â оÑделÑнÑй кÑиÑеÑий ÑоÑмÑ, а не ÑилÑÑÑаÑÐ¸Ñ Ñипов внÑÑÑи гÑÑпп.',\n 'РпÑимеÑе Ð´Ð»Ñ frontend аÑÑибÑÑ data-product-filter-trigger ÑÑавиÑÑÑ Ð½Ð° обÑÑÑÐºÑ ÑмонÑиÑованного UIChip; ÑобÑÑие infotecs-ui-click вÑплÑÐ²Ð°ÐµÑ Ð¾Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸.',\n 'СкÑÐ¸Ð¿Ñ frontend обÑабаÑÑÐ²Ð°ÐµÑ ÑобÑÑÐ¸Ñ product-filters:apply и product-filters:error на обÑÑÑке Ñипа; пÑÐ¸Ð¼ÐµÑ Ð½Ðµ менÑÐµÑ ÑпиÑок пÑодÑкÑов.',\n 'ФоÑÐ¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ заÑегиÑÑÑиÑоваÑÑ Ð²Ð¾ вÑÐµÐ¼Ñ ÑабоÑÑ ÑÑÑаниÑÑ ÑеÑез setForm(), но ÑÑо менÑÐµÑ Ð¾Ð±Ñий каÑалог ÑоÑм. ÐдеÑÑ Ñаблон подгоÑовлен в frontend-cabinet, а ваÑианÑÑ Ð¿ÐµÑедаÑÑÑÑ Ð¿Ñи оÑкÑÑÑии из frontend.',\n ],\n});\n\nexport const run = async ({\n appliedFilters = {},\n globalTarget,\n log,\n namespaceKey,\n onFiltersApplied = _ => null,\n own,\n}) => {\n const services = globalTarget[namespaceKey];\n const modalManager = services?.ModalManagerV2;\n const formManager = services?.FormManager;\n if (!modalManager || !formManager) {\n throw new Error('ModalManagerV2 and FormManager are required');\n }\n\n await Promise.all([modalManager.whenReady(), formManager.whenReady()]);\n const instance = own(await formManager.open(FORM_ID, {\n query: appliedFilters.query ?? '',\n selected: appliedFilters.selected ?? {},\n }, {\n mount: modalManager,\n onSubmit: payload => {\n const result = payload?.sendData?.data ?? null;\n const filters = readProductFilters(result);\n onFiltersApplied(filters);\n log('ÐÑиÑеÑии ÑилÑÑÑа пеÑÐµÐ´Ð°Ð½Ñ Ð¿Ð¾ÑÑебиÑелÑ', { filters, result });\n return modalFlow.close(result);\n },\n presentation: { preset: 'sheet', side: 'right' },\n }));\n log('ФилÑÑÑ Ð¾ÑкÑÑÑ Ð¿Ð¾ ID гоÑовой ÑоÑмÑ', {\n formId: FORM_ID,\n instanceId: instance.instanceId,\n modalId: instance.mountResult.id,\n });\n};\n\nexport default recipe;\n","./mmv2-l01-repeated-open.js":"export const recipe = Object.freeze({\n description: 'ÐоказÑÐ²Ð°ÐµÑ ÑазниÑÑ Ð¼ÐµÐ¶Ð´Ñ Ð¿Ð¾Ð²ÑоÑнÑм вÑзовом open() Ð´Ð»Ñ ÑÑÑеÑÑвÑÑÑего ÑкземплÑÑа и Ñозданием нового окна поÑле закÑÑÑиÑ.',\n expected: [\n 'ÐовÑоÑнÑй open() до закÑÑÑÐ¸Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÑ ÑÐ¾Ñ Ð¶Ðµ обÑÐµÐºÑ Ð¸ не ÑоздаÑÑ Ð´ÑÐ±Ð»Ð¸ÐºÐ°Ñ Ð¾ÐºÐ½Ð°.',\n 'Ðнопка «ÐакÑÑÑÑ Ð¸ оÑкÑÑÑÑ Ð½Ð¾Ð²Ñй» оконÑаÑелÑно завеÑÑÐ°ÐµÑ Ð¿ÐµÑвÑй ÑкземплÑÑ.',\n 'СледÑÑÑий prepare() ÑоздаÑÑ Ð½Ð¾Ð²Ñй instanceId Ð´Ð»Ñ Ñого же Ñипа модалÑного окна.',\n ],\n group: 'ÐизненнÑй Ñикл',\n id: 'MMV2-L01',\n safety: 'read-only',\n tags: ['repeated-open', 'closed', 'identity'],\n title: 'ÐовÑоÑно оÑкÑÑÑÑ Ð¾ÐºÐ½Ð¾ поÑле закÑÑÑиÑ',\n useWhen: 'ЧÑÐ¾Ð±Ñ Ð½Ðµ ÑоздаваÑÑ Ð´ÑбликаÑÑ Ñже оÑкÑÑÑого окна и пÑавилÑно наÑинаÑÑ Ð½Ð¾Ð²Ñй жизненнÑй Ñикл поÑле его закÑÑÑиÑ.',\n});\n\nexport const run = async ({ log, manager, own, signal }) =>
1 {\n const instance = own(await manager.prepare('ModalSuccess', {\n messages: ['ÐеÑвÑй ÑкземплÑÑ.'],\n }));\n instance\n .setText('title', 'MMV2-L01: пеÑвÑй ÑкземплÑÑ')\n .setAction({\n closePolicy: 'never',\n id: 'reopen',\n role: 'primary',\n text: 'ÐакÑÑÑÑ Ð¸ оÑкÑÑÑÑ Ð½Ð¾Ð²Ñй',\n })\n .setActionHandler('reopen', ({ flow }) =>\n flow.close({ reopen: true }));\n\n const opened = await manager.open(instance);\n const repeated = await manager.open(instance);\n log('ÐовÑоÑнÑй open() веÑнÑл ÑÑÑеÑÑвÑÑÑий ÑкземплÑÑ', {\n identity: repeated === opened,\n instanceId: instance.instanceId,\n });\n\n void instance.closed.then(async ({ result }) => {\n if (!result?.reopen || signal.aborted) return;\n\n const fresh = own(await manager.prepare('ModalSuccess', {\n messages: ['ÐÑо новÑй ÑкземплÑÑ, ÑозданнÑй поÑле полного закÑÑÑÐ¸Ñ Ð¿ÑедÑдÑÑего.'],\n }));\n fresh\n .setText('title', 'MMV2-L01: новÑй ÑкземплÑÑ')\n .setAction({ id: 'close', role: 'primary', text: 'ÐакÑÑÑÑ' });\n await manager.open(fresh);\n log('ÐоÑле закÑÑÑÐ¸Ñ Ñоздан новÑй ÑкземплÑÑ', {\n changed: fresh.instanceId !== instance.instanceId,\n first: instance.instanceId,\n fresh: fresh.instanceId,\n });\n }).catch(error => log('Ðе ÑдалоÑÑ Ð¾ÑкÑÑÑÑ Ð½Ð¾Ð²Ñй ÑкземплÑÑ', {\n code: error?.code ?? null,\n message: error?.message ?? String(error),\n }, 'error'));\n};\n","./mmv2-l02-stack.js":"export const recipe = Object.freeze({\n description: 'ÐÑкÑÑÐ²Ð°ÐµÑ Ð¾ÐºÐ½Ð¾ подÑвеÑждениÑ, заÑем показÑÐ²Ð°ÐµÑ Ð¿Ð¾Ð²ÐµÑÑ
него окно оÑибки и ÑоÑ
ÑанÑÐµÑ Ð½Ð¸Ð¶Ð½Ð¸Ð¹ ÑкземплÑÑ.',\n expected: [\n 'Ðижнее окно ModalPrompt полÑÑÐ°ÐµÑ ÑÑаÑÑÑ covered â оно пеÑекÑÑÑо, но оÑÑаÑÑÑÑ ÑмонÑиÑованнÑм.',\n 'ÐоÑле закÑÑÑÐ¸Ñ Ð²ÐµÑÑ
него ModalError нижнее окно Ñнова полÑÑÐ°ÐµÑ ÑÑаÑÑÑ open и ÑÑановиÑÑÑ Ð´Ð¾ÑÑÑпнÑм.',\n 'СÑек показа и activeModalId вÑегда ÑказÑваÑÑ Ð½Ð° ÑакÑиÑеÑкий поÑÑдок окон.',\n ],\n group: 'ÐизненнÑй Ñикл',\n id: 'MMV2-L02',\n safety: 'read-only',\n tags: ['stack', 'covered', 'reveal'],\n title: 'ÐÑкÑÑÑÑ Ð¾ÐºÐ½Ð¾ повеÑÑ
дÑÑгого',\n useWhen: 'ÐÐ»Ñ Ð¿Ð¾ÑледоваÑелÑноÑÑи завиÑимÑÑ
окон, где нижнее окно должно ÑоÑ
ÑаниÑÑ Ð²Ð²ÐµÐ´ÑннÑе даннÑе, пока полÑзоваÑÐµÐ»Ñ ÑабоÑÐ°ÐµÑ Ñ Ð²ÐµÑÑ
ним.',\n});\n\nexport const run = async ({ log, manager, own }) => {\n const prompt = own(await manager.prepare('ModalPrompt', {\n details: 'ÐакÑойÑе веÑÑ
нÑÑ Ð¾ÑибкÑ, ÑÑÐ¾Ð±Ñ Ð²ÐµÑнÑÑÑÑÑ ÑÑда.',\n }));\n prompt.setText('title', 'MMV2-L02: нижнее окно подÑвеÑждениÑ');\n await manager.open(prompt);\n\n const error = own(await manager.prepare('ModalError', {\n messages: ['ÐÑо веÑÑ
нее окно в ÑÑеке показа.'],\n }));\n error.setText('title', 'MMV2-L02: веÑÑ
нÑÑ Ð¾Ñибка');\n await manager.open(error);\n\n log('Ðва окна оÑкÑÑÑÑ ÑлоÑми', {\n error: error.getState(),\n manager: manager.getState(),\n prompt: prompt.getState(),\n });\n};\n","./mmv2-l03-replace.js":"export const recipe = Object.freeze({\n description: 'ÐоÑле подÑвеÑÐ¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°Ð¼ÐµÐ½ÑÐµÑ ÑекÑÑее окно ModalPrompt новÑм окном ModalSuccess без пÑомежÑÑоÑного пÑÑÑого ÑоÑÑоÑниÑ.',\n expected: [\n 'СнаÑала оÑкÑÑваеÑÑÑ Ñелевое окно, заÑем иÑÑ
одное закÑÑваеÑÑÑ Ñ Ð¿ÑиÑиной replaced.',\n 'ÐоÑле пеÑеÑ
ода в ÑÑеке показа оÑÑаÑÑÑÑ ÑолÑко ModalSuccess.',\n 'ÐаÑалог ÑегиÑÑÑиÑÑÐµÑ Ð½Ð¾Ð²Ð¾Ðµ окно как пÑинадлежаÑее кейÑÑ Ð¸ безопаÑно закÑÑÐ²Ð°ÐµÑ ÐµÐ³Ð¾ пÑи ÑбÑоÑе.',\n ],\n group: 'ÐизненнÑй Ñикл',\n id: 'MMV2-L03',\n safety: 'read-only',\n tags: ['replace', 'flow.open', 'ownership'],\n title: 'ÐамениÑÑ Ð¾Ð´Ð½Ð¾ окно дÑÑгим',\n useWhen: 'Ðогда ÑледÑÑÑий Ñаг пÑоÑеÑÑа должен полноÑÑÑÑ Ð·Ð°Ð¼ÐµÐ½Ð¸ÑÑ ÑекÑÑее окно, напÑÐ¸Ð¼ÐµÑ Ð¿Ð¾Ð´ÑвеÑждение â ÑообÑением об ÑÑпеÑ
е.',\n});\n\nexport const run = async ({ log, manager, own, signal }) =>
1 {\n const prompt = own(await manager.prepare('ModalPrompt', {\n details: 'ÐажмиÑе подÑвеÑждение: ÑÑо окно бÑÐ´ÐµÑ Ð·Ð°Ð¼ÐµÐ½ÐµÐ½Ð¾ ÑообÑением об ÑÑпеÑ
е.',\n }));\n prompt\n .setText('title', 'MMV2-L03: иÑÑ
одное окно подÑвеÑждениÑ')\n .setActionHandler('confirm', ({ flow }) => flow.open(\n 'ModalSuccess',\n { messages: ['Ðкно подÑвеÑÐ¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°Ð¼ÐµÐ½ÐµÐ½Ð¾ без пÑомежÑÑоÑного пÑÑÑого ÑÑека.'] },\n { transition: 'replace' },\n ));\n\n void prompt.closed.then(result => {\n if (result.reason !== 'replaced' || signal.aborted) return;\n const target = manager.getInstance('ModalSuccess');\n if (target) own(target);\n log('Ðамена одного окна дÑÑгим завеÑÑена', {\n closed: result,\n manager: manager.getState(),\n targetInstanceId: target?.instanceId ?? null,\n });\n });\n\n await manager.open(prompt);\n log('Ðкно подÑвеÑÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð´Ð»Ñ Ð¿ÐµÑеÑ
ода', prompt.getState());\n};\n","./mmv2-l04-timeout-close.js":"export const recipe = Object.freeze({\n description: 'ÐÑкÑÑÐ²Ð°ÐµÑ ModalSuccess и ÑеÑез 3 ÑекÑÐ½Ð´Ñ Ð²ÑзÑÐ²Ð°ÐµÑ instance.close(). Раннее закÑÑÑие или ÑбÑÐ¾Ñ ÐºÐµÐ¹Ñа оÑменÑÐµÑ ÑаймеÑ.',\n expected: [\n 'Ðкно закÑÑваеÑÑÑ Ð°Ð²ÑомаÑиÑеÑки ÑеÑез 3 ÑекÑÐ½Ð´Ñ Ð¿Ð¾Ñле показа.',\n 'РжÑÑнале ÑезÑлÑÑÐ°Ñ Ð·Ð°ÐºÑÑÑÐ¸Ñ ÑодеÑÐ¶Ð¸Ñ result.timedOut: true; reason оÑÑаÑÑÑÑ programmatic.',\n 'ÐÑи закÑÑÑии кнопкой или кÑеÑÑиком ÑанÑÑе ÑÑока ÑÐ°Ð¹Ð¼ÐµÑ Ð¾ÑменÑеÑÑÑ.',\n 'ÐовÑоÑнÑй запÑÑк ÑоздаÑÑ Ð½Ð¾Ð²Ñй ÑаймеÑ. СбÑÐ¾Ñ ÐºÐµÐ¹Ñа оÑиÑÐ°ÐµÑ ÐµÐ³Ð¾.',\n ],\n group: 'ÐизненнÑй Ñикл',\n id: 'MMV2-L04',\n safety: 'read-only',\n tags: ['timeout', 'setTimeout', 'close', 'onDispose'],\n title: 'ÐакÑÑÑÑ Ð¾ÐºÐ½Ð¾ по ÑаймеÑÑ',\n useWhen: 'ÐÐ»Ñ ÐºÑаÑкого ÑообÑениÑ, коÑоÑое должно иÑÑезнÑÑÑ Ð°Ð²ÑомаÑиÑеÑки ÑеÑез заданное вÑемÑ.',\n warnings: [\n 'Ð¢Ð°Ð¹Ð¼ÐµÑ Ð²ÑзÑÐ²Ð°ÐµÑ instance.close(), а не flow.close(): flow нÑжно веÑнÑÑÑ Ð¸Ð· обÑабоÑÑика дейÑÑвиÑ.',\n 'ÐакÑÑÑие пÑоÑ
Ð¾Ð´Ð¸Ñ Ð¾Ð±ÑÑнÑй beforeClose. ÐÑли обÑабоÑÑик запÑеÑÐ¸Ñ Ð·Ð°ÐºÑÑÑие, повÑоÑной попÑÑки по ÑаймеÑÑ Ð½Ðµ бÑдеÑ.',\n ],\n});\n\nexport const run = async ({ log, manager, own, registerCleanup, signal }) => {\n const instance = own(await manager.prepare('ModalSuccess', {\n message: 'Ðкно закÑоеÑÑÑ ÑеÑез 3 ÑекÑндÑ. Ðожно закÑÑÑÑ ÐµÐ³Ð¾ ÑанÑÑе кнопкой или кÑеÑÑиком.',\n title: 'MMV2-L04: закÑÑÑие по ÑаймеÑÑ',\n }));\n let timerId;\n const cancelTimeout = _ => clearTimeout(timerId);\n const unregisterCleanup = registerCleanup(cancelTimeout);\n instance.onDispose(_ => {\n cancelTimeout();\n unregisterCleanup();\n });\n\n void instance.closed.then(outcome => {\n if (signal.aborted) return;\n log(outcome.result?.timedOut\n ? 'Ðкно закÑÑÑо по ÑаймеÑÑ'\n : 'Ðкно закÑÑÑо ÑанÑÑе ÑÑока; ÑÐ°Ð¹Ð¼ÐµÑ Ð¾ÑменÑн', outcome);\n });\n\n await manager.open(instance);\n if (signal.aborted || ['closing', 'closed'].includes(instance.status)) return;\n\n timerId = setTimeout(_ => {\n instance.close({ timedOut: true })\n .then(closed => {\n if (!closed && !signal.aborted) log('ÐакÑÑÑие по ÑаймеÑÑ Ð¾Ñменено');\n })\n .catch(error => {\n if (!signal.aborted) log('ÐÑибка закÑÑÑÐ¸Ñ Ð¿Ð¾ ÑаймеÑÑ', { message: error.message });\n });\n }, 3000);\n log('Ð¢Ð°Ð¹Ð¼ÐµÑ Ð·Ð°Ð¿ÑÑен: 3 ÑекÑндÑ', { instanceId: instance.instanceId });\n};\n","./mmv2-o01-events-state.js":"export const recipe = Object.freeze({\n description: 'ÐодпиÑÑваеÑÑÑ Ð½Ð° Ñнимки ÑоÑÑоÑÐ½Ð¸Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑа и на пÑблиÑнÑе ÑобÑÑÐ¸Ñ ÑÑÑаниÑÑ, ÑÑÐ¾Ð±Ñ Ð¿Ð¾ÐºÐ°Ð·Ð°ÑÑ Ð¾Ð±Ð° ÑпоÑоба наблÑдениÑ.',\n expected: [\n 'ÐодпиÑÑик ÑÑÐ°Ð·Ñ Ð¿Ð¾Ð»ÑÑÐ°ÐµÑ ÑекÑÑий Ñнимок и заÑем каждÑй Ñнимок Ñ Ð½Ð¾Ð²Ð¾Ð¹ revision.',\n 'DOM CustomEvent имеÑÑ Ð¿ÑеÑÐ¸ÐºÑ modal
1-manager-v2 и ÑодеÑÐ¶Ð°Ñ ÑеÑиализÑемÑе даннÑе в поле detail.',\n 'СбÑÐ¾Ñ ÐºÐµÐ¹Ñа оÑпиÑÑÐ²Ð°ÐµÑ ÑÑнкÑиÑ-наблÑдаÑÐµÐ»Ñ Ð¸ ÑдалÑÐµÑ Ð²Ñе DOM-обÑабоÑÑики.',\n ],\n group: 'СоÑÑоÑние и ÑобÑÑиÑ',\n id: 'MMV2-O01',\n safety: 'read-only',\n tags: ['subscribe', 'events', 'revision'],\n title: 'ÐаблÑдаÑÑ ÑоÑÑоÑние и ÑобÑÑиÑ',\n useWhen: 'ÐÐ»Ñ Ð´Ð¸Ð°Ð³Ð½Ð¾ÑÑики жизненного Ñикла окон или подклÑÑÐµÐ½Ð¸Ñ Ð²Ð½ÐµÑнего наблÑдаÑелÑ, коÑоÑÑй ÑиÑÐ°ÐµÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ, но не ÑпÑавлÑÐµÑ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑом.',\n});\n\nexport const run = async ({\n eventTarget,\n log,\n manager,\n own,\n registerCleanup,\n}) => {\n const unsubscribe = manager.subscribe(state => {\n log('ÐодпиÑÑик менеджеÑа полÑÑил Ñнимок ÑоÑÑоÑниÑ', {\n activeModalId: state.activeModalId,\n openCount: state.openCount,\n revision: state.revision,\n stack: state.stack,\n });\n });\n registerCleanup(unsubscribe);\n\n const eventNames = [\n 'opened',\n 'covered',\n 'revealed',\n 'closed',\n 'action-start',\n 'action-completed',\n ].map(name => `modal-manager-v2:${name}`);\n const onEvent = event => log(`DOM event ${event.type}`, event.detail);\n eventNames.forEach(name => eventTarget?.addEventListener(name, onEvent));\n registerCleanup(_ => eventNames.forEach(name =>\n eventTarget?.removeEventListener(name, onEvent)));\n\n const instance = own(await manager.prepare('ModalSuccess', {\n messages: ['ÐакÑойÑе окно и ÑÑавниÑе запиÑи о ÑнимкаÑ
ÑоÑÑоÑÐ½Ð¸Ñ Ð¸ DOM-ÑобÑÑиÑÑ
в жÑÑнале кейÑа.'],\n }));\n instance.setText('title', 'MMV2-O01: наблÑдаемоÑÑÑ');\n await manager.open(instance);\n};\n","./mmv2-o02-store.js":"export const recipe = Object.freeze({\n description: 'ÐоказÑÐ²Ð°ÐµÑ Ð´Ð²Ð° меÑÑа Ð´Ð»Ñ Ð²ÑеменнÑÑ
даннÑÑ
: обÑÑÑ Ð¸Ð¼ÐµÐ½Ð¾Ð²Ð°Ð½Ð½ÑÑ Ð¾Ð±Ð»Ð°ÑÑÑ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑа и Ñ
ÑанилиÑе оÑделÑного ÑкземплÑÑа окна.',\n expected: [\n 'ÐбÑие знаÑÐµÐ½Ð¸Ñ ÑиÑаÑÑÑÑ ÑолÑко по Ñвно Ð·Ð°Ð´Ð°Ð½Ð½Ð¾Ð¼Ñ Ð¸Ð¼ÐµÐ½Ð¸ облаÑÑи (manager scope), поÑÑÐ¾Ð¼Ñ ÑазнÑе инÑегÑаÑии не ÑмеÑиваÑÑ Ð´Ð°Ð½Ð½Ñе.',\n 'ÐнаÑÐµÐ½Ð¸Ñ ÑкземплÑÑа доÑÑÑÐ¿Ð½Ñ ÑолÑко ÑеÑез ÑооÑвеÑÑÑвÑÑÑий ModalInstance и намеÑенно не вÑ
одÑÑ Ð² пÑблиÑнÑй Ñнимок ÑоÑÑоÑниÑ.',\n 'ÐакÑÑÑие ÑдалÑÐµÑ Ð´Ð°Ð½Ð½Ñе ÑкземплÑÑа авÑомаÑиÑеÑки, а ÑбÑÐ¾Ñ ÐºÐµÐ¹Ñа Ñвно оÑиÑÐ°ÐµÑ ÑозданнÑÑ Ð¸Ð¼ обÑÑÑ Ð¾Ð±Ð»Ð°ÑÑÑ.',\n ],\n group: 'СоÑÑоÑние и ÑобÑÑиÑ',\n id: 'MMV2-O02',\n safety: 'read-only',\n tags: ['store', 'scope', 'cleanup'],\n title: 'Ð¥ÑаниÑÑ Ð²ÑеменнÑе даннÑе в ÑазнÑÑ
облаÑÑÑÑ
',\n useWhen: 'Ðогда одним вÑеменнÑм даннÑм нÑжно жиÑÑ Ð´Ð¾ закÑÑÑÐ¸Ñ ÐºÐ¾Ð½ÐºÑеÑного окна, а дÑÑгим â долÑÑе и под оÑвеÑÑÑвенноÑÑÑÑ Ð¸Ð½ÑегÑаÑии.',\n});\n\nexport const run = async ({\n log,\n manager,\n own,\n registerCleanup,\n}) => {\n const scope = 'modal-manager-v2-catalog:MMV2-O02';\n manager.setStore(scope, {\n recipeId: 'MMV2-O02',\n source: 'catalog',\n });\n registerCleanup(_ => manager.clearStore(scope));\n\n const instance = own(await manager.prepare('ModalSuccess', {\n messages: ['ÐнаÑÐµÐ½Ð¸Ñ Ð²ÑеменнÑÑ
Ñ
ÑÐ°Ð½Ð¸Ð»Ð¸Ñ Ð½Ðµ попадаÑÑ Ð² пÑблиÑнÑй Ñнимок ÑоÑÑоÑÐ½Ð¸Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑа.'],\n }));\n instance\n .setText('title', 'MMV2-O02: облаÑÑи вÑеменнÑÑ
даннÑÑ
')\n .setStore({\n localStep: 1,\n owner: instance.instanceId,\n })\n .onDispose(_ => log('ÐблаÑÑÑ Ð´Ð°Ð½Ð½ÑÑ
ÑкземплÑÑа оÑиÑена пÑи его оÑвобождении'));\n\n await manager.open(instance);\n log('СÑавнение двÑÑ
облаÑÑей вÑеменнÑÑ
даннÑÑ
', {\n instanceStore: instance.getStore(['localStep', 'owner']),\n managerState: manager.getState(),\n managerStore: manager.getStore(scope, ['recipeId', 'source']),\n });\n};\n","./mmv2-p01-presentation.js":"export const recipe = Object.freeze({\n description: 'ÐÑкÑÑÐ²Ð°ÐµÑ ÑÑи ÑÑандаÑÑнÑÑ
окна ÑлоÑми, ÑÑÐ¾Ð±Ñ Ð²Ð¸Ð·ÑалÑно ÑÑавниÑÑ Ð²Ð°ÑианÑÑ ÑазмеÑÐµÐ½Ð¸Ñ sheet, dialog и dialog-lg.',\n expected: [\n 'Ð ÑÑеке показа одновÑеменно наÑ
одÑÑÑÑ ÑÑи ÑкземплÑÑа Ñ ÑазнÑми ваÑианÑами внеÑнего вида
1(presentation preset).',\n 'СнаÑала закÑÑваеÑÑÑ Ð²ÐµÑÑ
нее болÑÑое окно dialog-lg, заÑем ÑÑановÑÑÑÑ Ð´Ð¾ÑÑÑÐ¿Ð½Ñ dialog и sheet.',\n 'ÐеÑекÑÑÑÑе окна ÑоÑ
ÑанÑÑÑÑÑ Ð² DOM и ÑÐ²Ð¾Ñ ÑоÑÑоÑние; закÑÑÑие веÑÑ
него ÑÐ»Ð¾Ñ Ð½Ðµ ÑоздаÑÑ Ð¸Ñ
заново.',\n ],\n group: 'ÐнеÑний вид',\n id: 'MMV2-P01',\n safety: 'read-only',\n tags: ['sheet', 'dialog', 'dialog-lg'],\n title: 'СÑавниÑÑ Ð²Ð°ÑианÑÑ ÑазмеÑÐµÐ½Ð¸Ñ Ð¾ÐºÐ¾Ð½',\n useWhen: 'ЧÑÐ¾Ð±Ñ Ð²ÑбÑаÑÑ Ð¿Ð¾Ð´Ñ
одÑÑий ÑÐ°Ð·Ð¼ÐµÑ Ð¸ ÑаÑположение модалÑного окна и пÑовеÑиÑÑ Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ðµ неÑколÑкиÑ
ÑлоÑв.',\n});\n\nexport const run = async ({ log, manager, own }) => {\n const sheet = own(await manager.prepare('ModalError', {\n messages: ['Ðижний Ñлой иÑполÑзÑÐµÑ Ð²Ð°ÑÐ¸Ð°Ð½Ñ sheet.'],\n }));\n sheet.setText('title', 'ÐаÑÐ¸Ð°Ð½Ñ ÑазмеÑениÑ: sheet');\n\n const dialog = own(await manager.prepare('ModalPrompt', {\n details: 'СÑедний Ñлой иÑполÑзÑÐµÑ Ð²Ð°ÑÐ¸Ð°Ð½Ñ dialog.',\n }));\n dialog\n .setText('title', 'ÐаÑÐ¸Ð°Ð½Ñ ÑазмеÑениÑ: dialog')\n .setPresentation({ preset: 'dialog', size: 'sm' });\n\n const dialogLarge = own(await manager.prepare('ModalSuccess', {\n messages: ['ÐеÑÑ
ний Ñлой иÑполÑзÑÐµÑ Ð²Ð°ÑÐ¸Ð°Ð½Ñ dialog-lg. ÐакÑÑвайÑе окна ÑвеÑÑ
Ñ Ð²Ð½Ð¸Ð·.'],\n }));\n dialogLarge\n .setText('title', 'ÐаÑÐ¸Ð°Ð½Ñ ÑазмеÑениÑ: dialog-lg')\n .setPresentation({ preset: 'dialog-lg' });\n\n await manager.open(sheet);\n await manager.open(dialog);\n await manager.open(dialogLarge);\n log('СÑек из ÑÑÑÑ
ваÑианÑов ÑазмеÑÐµÐ½Ð¸Ñ ÑÑоÑмиÑован', manager.getState());\n};\n","./mmv2-p02-dynamic.js":"export const recipe = Object.freeze({\n description: 'ÐÑкÑÑÐ²Ð°ÐµÑ Ð¾ÐºÐ½Ð¾, а заÑем менÑÐµÑ ÐµÐ³Ð¾ заголовок, ÑодеÑжимое, ÑазмеÑ, пÑавила закÑÑÑÐ¸Ñ Ð¸ пÑблиÑнÑй CSS-клаÑÑ.',\n expected: [\n 'ЧеÑез 700 Ð¼Ñ ÑодеÑжимое и заголовок менÑÑÑÑÑ, но instanceId оÑÑаÑÑÑÑ Ð¿Ñежним.',\n 'Ð Ð°Ð·Ð¼ÐµÑ Ð¸ пÑавила закÑÑÑÐ¸Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÑÑÑÑÑ Ð±ÐµÐ· повÑоÑного ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñа (remount).',\n 'ÐÑблиÑнÑй CSS-клаÑÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÐµÑ Ð²Ð¸Ð´Ð¸Ð¼ÑÑ ÑÐ°Ð¼ÐºÑ Ð¸ ÑдалÑеÑÑÑ Ð²Ð¼ÐµÑÑе Ñ ÑкземплÑÑом окна.',\n ],\n group: 'ÐнеÑний вид',\n id: 'MMV2-P02',\n safety: 'read-only',\n tags: ['reactivity', 'setProps', 'setClasses'],\n title: 'ÐбновиÑÑ Ñже оÑкÑÑÑое окно',\n useWhen: 'Ðогда оÑкÑÑÑое окно должно показаÑÑ Ð½Ð¾Ð²Ñе даннÑе, не ÑеÑÑÑ Ð²Ð²ÐµÐ´ÑннÑе знаÑÐµÐ½Ð¸Ñ Ð¸ дÑÑгое локалÑное ÑоÑÑоÑние компоненÑа.',\n});\n\nexport const run = async ({ log, manager, own, wait }) => {\n const instance = own(await manager.prepare('ModalError', {\n details: 'Ðбновление пÑоизойдÑÑ ÑеÑез 700 мÑ.',\n messages: ['ÐаÑалÑное ÑодеÑжимое.'],\n }));\n instance.setText('title', 'MMV2-P02: наÑалÑное ÑоÑÑоÑние');\n await manager.open(instance);\n\n if (!await wait(700) || instance.status === 'closed') return;\n\n instance\n .setText('title', 'MMV2-P02: окно обновлено без пеÑеÑозданиÑ')\n .setProps({\n details: 'ÐденÑиÑикаÑÐ¾Ñ ÑкземплÑÑа instanceId ÑоÑ
ÑанилÑÑ.',\n messages: ['СодеÑжимое, ÑазмеÑ, пÑавила закÑÑÑÐ¸Ñ Ð¸ CSS-клаÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ñ Ð±ÐµÐ· пеÑеÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾ÐºÐ½Ð°.'],\n })\n .setPresentation({\n dismiss: { backdrop: true },\n size: 'lg',\n })\n .setClasses({\n surface: 'modal-manager-v2-catalog__demo-surface',\n });\n\n log('ÐкземплÑÑ Ð¾Ð±Ð½Ð¾Ð²Ð»Ñн без пеÑеÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñа', instance.getState());\n};\n","./mmv2-p03-disabled-action.js":"import {\n defineComponent,\n h,\n markRaw,\n ref,\n watch,\n} from 'vue';\n\nimport UiCheckbox from '@ui/Checkbox/index.vue';
1\n\nexport const bindActionDisabled = (manager, instance, actionId, isBlocked) => {\n const syncButton = _ => {\n const state = instance.getState();\n if (['closing', 'closed'].includes(state.status)) return;\n if (state.busyActionId === actionId) return;\n\n const action = instance.getAction(actionId);\n if (action && action.disabled !== isBlocked.value) {\n instance.setAction({ id: actionId, disabled: isBlocked.value });\n }\n };\n\n const stopWatch = watch(isBlocked, syncButton, { flush: 'sync' });\n const unsubscribe = manager.subscribe(syncButton);\n instance.onDispose(_ => {\n stopWatch();\n unsubscribe();\n });\n};\n\nexport const recipe = Object.freeze({\n description: 'Флаг isBlocked Ñ
ÑаниÑÑÑ Ð²Ð½Ðµ компоненÑа окна. Флажок менÑÐµÑ ÐµÐ³Ð¾ знаÑение, а watch обновлÑÐµÑ disabled кнопки ÑеÑез instance.setAction().',\n expected: [\n 'ÐÑи оÑкÑÑÑии Ñлажок ÑÑÑановлен, а кнопка «ÐодÑвеÑдиÑÑ» заблокиÑована.',\n 'СнимиÑе Ñлажок: кнопка ÑÑÐ°Ð½ÐµÑ Ð´Ð¾ÑÑÑпна. УÑÑановиÑе Ñнова: она заблокиÑÑеÑÑÑ Ð±ÐµÐ· пеÑеÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾ÐºÐ½Ð°.',\n 'ÐажмиÑе «ÐодÑвеÑдиÑÑ» и измениÑе Ñлаг во вÑÐµÐ¼Ñ Ð¿ÑовеÑки. ÐоÑле завеÑÑÐµÐ½Ð¸Ñ ÐºÐ½Ð¾Ð¿ÐºÐ° полÑÑÐ¸Ñ Ð¿Ð¾Ñледнее знаÑение Ñлага.',\n 'ÐакÑÑÑие окна ÑÐ½Ð¸Ð¼Ð°ÐµÑ Ð¿Ð¾Ð´Ð¿Ð¸Ñки; повÑоÑнÑй запÑÑк наÑÐ¸Ð½Ð°ÐµÑ ÐºÐµÐ¹Ñ Ñ Ð¸ÑÑ
одного ÑоÑÑоÑниÑ.',\n ],\n group: 'ÐнеÑний вид',\n id: 'MMV2-P03',\n safety: 'read-only',\n tags: ['setAction', 'disabled', 'boolean', 'watch'],\n title: 'ÐлокиÑоваÑÑ ÐºÐ½Ð¾Ð¿ÐºÑ Ð¿Ð¾ ÑлагÑ',\n useWhen: 'Ðогда доÑÑÑпноÑÑÑ Ð´ÐµÐ¹ÑÑÐ²Ð¸Ñ Ð·Ð°Ð²Ð¸ÑÐ¸Ñ Ð¾Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ÑоÑмÑ, ÑезÑлÑÑаÑа пÑовеÑки или дÑÑгого ÑеакÑивного знаÑениÑ.',\n warnings: [\n 'disabled пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ boolean. ÐеÑедаÑа ref или ÑÑнкÑии вмеÑÑо знаÑÐµÐ½Ð¸Ñ Ð½Ðµ ÑоздаÑÑ Ð¿Ð¾Ð´Ð¿Ð¸ÑкÑ.',\n 'ÐÑполнÑÑÑийÑÑ action менÑÑÑ Ð½ÐµÐ»ÑзÑ. ÐодпиÑка на ÑоÑÑоÑние менеджеÑа пÑÐ¸Ð¼ÐµÐ½Ð¸Ñ Ð¾Ñложенное знаÑение поÑле его завеÑÑениÑ.',\n ],\n});\n\nexport const run = async ({ log, manager, own }) => {\n const isBlocked = ref(true);\n const message = ref('СнимиÑе Ñлажок, ÑÑÐ¾Ð±Ñ ÑазÑеÑиÑÑ Ð¿Ð¾Ð´ÑвеÑждение.');\n const content = markRaw(defineComponent({\n name: 'RecipeDisabledAction',\n setup: _ => _ => h('div', [\n h(UiCheckbox, {\n params: {\n id: 'mmv2-disabled-action-flag',\n model: isBlocked.value,\n texts: { label: 'ÐлокиÑоваÑÑ ÐºÐ½Ð¾Ð¿ÐºÑ Ð¿Ð¾Ð´ÑвеÑждениÑ' },\n },\n onChange: event => { isBlocked.value = Boolean(event.model); },\n }),\n h('p', `isBlocked: ${isBlocked.value}`),\n h('p', { role: 'status' }, message.value),\n ]),\n }));\n const instance = own(await manager.prepare('ModalManagerV2CatalogApp/ModalRecipeContent', {\n contentComponent: content,\n }));\n\n instance\n .setText('title', 'MMV2-P03: кнопка завиÑÐ¸Ñ Ð¾Ñ Ñлага')\n .setPresentation({ size: 'sm' })\n .setAction({\n id: 'confirm',\n text: 'ÐодÑвеÑдиÑÑ',\n role: 'primary',\n closePolicy: 'never',\n })\n .setActionHandler('confirm', async ({ flow, onCleanup, signal }) => {\n message.value = 'ÐÑовеÑка вÑполнÑеÑÑÑ. Ðожно измениÑÑ Ñлаг.';\n const completed = await new Promise(resolve => {\n const timer = setTimeout(_ => resolve(true), 1500);\n const abort = _ => resolve(false);\n signal.addEventListener('abort', abort, { once: true });\n onCleanup(_ => {\n clearTimeout(timer);\n signal.removeEventListener('abort', abort);\n });\n });\n if (!completed || signal.aborted) return flow.stay();\n message.value = 'ÐÑовеÑка завеÑÑена. Ðнопка Ñнова завиÑÐ¸Ñ Ð¾Ñ Ñлага.';\n log('ÐодÑвеÑждение вÑполнено', { isBlocked: isBlocked.value });\n return flow.stay();\n });\n\n bindActionDisabled(manager, instance, 'confirm', isBlocked);\n await manager.open(instance);\n log('Ðнопка ÑвÑзана Ñ Ñлагом isBlocked', { instanceId: instance.instanceId });\n};\n","./mmv2-p04-anchored-panel.js":"export const recipe = Object.freeze({\n description: 'ÐÑкÑÑÐ²Ð°ÐµÑ Ð½ÐµÐ¼Ð¾Ð´Ð°Ð»ÑнÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ ÑÑдом Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¾Ð¹ запÑÑка. СÑÑаниÑа оÑÑаÑÑÑÑ Ð´Ð¾ÑÑÑпной; положение пеÑеÑÑиÑÑваеÑÑÑ Ð¿Ñи пÑокÑÑÑке и изменении ÑазмеÑа.',\n expected: [\n 'Фон не заÑемнÑеÑÑÑ, пÑокÑÑÑка ÑÑÑаниÑÑ Ð´Ð¾ÑÑÑпна.',\n 'Escape и клик ÑнаÑÑжи закÑÑваÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ; Ñ ÐºÑÐ°Ñ ÑкÑана она менÑÐµÑ ÑÑоÑонÑ.',\n 'ÐовÑоÑнÑй запÑÑк ÑоздаÑÑ Ð½Ð¾Ð²Ñй ÑкземплÑÑ Ð¿Ð¾Ñле закÑÑÑÐ¸Ñ Ð¿ÑедÑдÑÑего.',\n ],\n group: 'ÐнеÑний вид',\n id: 'MMV2-P04',\n safety: 'read-only',\n tags: ['anchored-dialog', 'popover', 'modal: false'],\n title: 'ÐемодалÑÐ½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»Ñ Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸',\n useWhen: 'ÐÐ»Ñ Ð¿Ð°Ð»Ð¸ÑÑ Ð¸ неболÑÑиÑ
вÑпомогаÑелÑнÑÑ
ÑоÑм на ÑÑÑаниÑе.',\n});
1\n\nexport const run = async ({ anchor, log, manager, own }) => {\n const instance = own(await manager.prepare('ModalPrompt', {\n details: 'ÐÑокÑÑÑиÑе ÑÑÑаниÑÑ: Ð¿Ð°Ð½ÐµÐ»Ñ ÑледÑÐµÑ Ð·Ð° кнопкой и оÑÑаÑÑÑÑ Ð²Ð½ÑÑÑи видимой облаÑÑи.',\n }));\n instance\n .setText('title', 'ÐемодалÑÐ½Ð°Ñ Ð¿Ð°Ð½ÐµÐ»Ñ')\n .setPresentation({ preset: 'anchored-dialog', modal: false, size: 'sm' })\n .setAnchor(anchor);\n await manager.open(instance);\n log('ÐÐ°Ð½ÐµÐ»Ñ Ð¾ÑкÑÑÑа без блокиÑовки ÑÑÑаниÑÑ', instance.getState());\n};\n","./mmv2-p05-owned-panel.js":"// dependencies: vue\nimport { defineComponent, h, markRaw, ref } from 'vue';\n\n// library\nimport { propMaker } from '@lib/vue';\n\n// composables\nimport { useBEM } from '@cms/useBEM';\n\n// components\nimport UiButton from '@ui/Button/index.vue';\n\nconst Content = markRaw(defineComponent({\n props: { openPanel: propMaker(Function, null, true) },\n setup: props => {\n const { $b } = useBEM('b-modal-v2');\n const count = ref(0);\n return _ => h('div', [\n h('p', `СÑÑÑÑик ÑодиÑелÑ: ${count.value}`),\n h('div', { class: $b`,actions` }, [\n h(UiButton, {\n buttonText: 'ÐзмениÑÑ ÑодиÑелÑ',\n type: 'secondary',\n onAction: _ => { count.value++; },\n }),\n h(UiButton, {\n buttonText: 'ÐÑкÑÑÑÑ Ð´Ð¾ÑеÑнÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ',\n type: 'secondary',\n onAction: payload => props.openPanel(payload.event.currentTarget),\n }),\n ]),\n ]);\n },\n}));\n\nexport const recipe = Object.freeze({\n description: 'ÐÑкÑÑÐ²Ð°ÐµÑ Ð¾Ð±ÑÑное окно, внÑÑÑи коÑоÑого можно вÑзваÑÑ Ð½ÐµÐ¼Ð¾Ð´Ð°Ð»ÑнÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ. РодиÑÐµÐ»Ñ ÑоÑ
ÑанÑÐµÑ ÑоÑÑоÑние, а ÑÑÑаниÑа оÑÑаÑÑÑÑ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñованной ÑодиÑелÑÑким окном.',\n expected: [\n 'СÑÑÑÑик ÑодиÑÐµÐ»Ñ Ð¼Ð¾Ð¶Ð½Ð¾ менÑÑÑ Ð¿Ñи оÑкÑÑÑой панели: модалÑноÑÑÑ ÑодиÑÐµÐ»Ñ Ð½Ðµ ÑÑиливаеÑÑÑ.',\n 'ÐеÑвÑй Escape закÑÑÐ²Ð°ÐµÑ Ð¿Ð°Ð½ÐµÐ»Ñ, ÑледÑÑÑий â ÑодиÑелÑÑкое окно.',\n 'ÐÑеÑÑик ÑодиÑÐµÐ»Ñ Ð·Ð°ÐºÑÑÐ²Ð°ÐµÑ Ð¾Ð±Ð° ÑкземплÑÑа; доÑеÑнÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ Ð¿Ð¾Ð»ÑÑÐ°ÐµÑ Ð¿ÑиÑÐ¸Ð½Ñ owner-closed.',\n ],\n group: 'ÐнеÑний вид',\n id: 'MMV2-P05',\n safety: 'read-only',\n tags: ['anchored-dialog', 'setOwner', 'nested', 'modal: false'],\n title: 'ÐÐ°Ð½ÐµÐ»Ñ Ð²Ð½ÑÑÑи модалÑного окна',\n useWhen: 'ÐÐ»Ñ Ð¿Ð°Ð»Ð¸ÑÑÑ Ð¸Ð»Ð¸ вÑпомогаÑелÑной ÑоÑÐ¼Ñ Ð² Ñже оÑкÑÑÑом диалоге.',\n});\n\nexport const run = async ({ log, manager, own }) => {\n let child = null;\n const parent = own(await manager.prepare('ModalManagerV2CatalogApp/ModalRecipeContent', {\n contentComponent: Content,\n contentProps: {\n openPanel: async anchor => {\n try {\n if (child && child.status !== 'closed') { await child.close(); return; }\n child = own(await manager.prepare('ModalPrompt', { details: 'РодиÑÐµÐ»Ñ Ð¾ÑÑаÑÑÑÑ Ð´Ð¾ÑÑÑпнÑм. ÐÑа Ð¿Ð°Ð½ÐµÐ»Ñ Ð¿ÑÐ¸Ð½Ð°Ð´Ð»ÐµÐ¶Ð¸Ñ ÐµÐ¼Ñ.' }));\n child\n .clearActions()\n .setText('title', 'ÐоÑеÑнÑÑ Ð¿Ð°Ð½ÐµÐ»Ñ')\n .setPresentation({ preset: 'anchored-dialog', modal: false, size: 'sm', dismiss: { outside: false } })\n .setAnchor(anchor)\n .setOwner(parent);\n await manager.open(child);\n } catch (error) {\n if (child && child.status !== 'closed') await child.close();\n log('ÐÐ°Ð½ÐµÐ»Ñ Ð½Ðµ оÑкÑÑлаÑÑ', { message: error.message }, 'error');\n }\n },\n },\n }));\n parent.setText('title', 'РодиÑелÑÑкое окно');\n await manager.open(parent);\n};\n","./mmv2-p06-anchored-modal.js":"export const recipe = Object.freeze({\n description: 'ÐÑполÑзÑÐµÑ ÑÑ Ð¶Ðµ пÑивÑÐ·ÐºÑ Ðº кнопке, но оÑкÑÑÐ²Ð°ÐµÑ Ð¿Ð¾Ð»Ð½Ð¾ÑеннÑй блокиÑÑÑÑий диалог ÑеÑез presentation.modal: true.',\n expected: [\n 'Ðкно пÑивÑзано к кнопке, Ñон заÑемнÑн и недоÑÑÑпен.',\n 'ФокÑÑ ÑдеÑживаеÑÑÑ Ð² диалоге; Escape и кÑеÑÑик закÑÑваÑÑ Ð¾ÐºÐ½Ð¾.',\n 'ÐоÑле закÑÑÑÐ¸Ñ Ð²Ð¾ÑÑÑанавливаÑÑÑÑ Ð¿ÑокÑÑÑка и ÑокÑÑ.',\n ],\n group: 'ÐнеÑний вид',\n id: 'MMV2-P06',\n safety: 'read-only',\n tags: ['anchored-dialog', 'modal: true'],\n title: 'ÐодалÑное окно Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸',\n useWhen: 'Ðогда диалог нÑжно ÑаÑположиÑÑ ÑÑдом Ñ Ð¸ÑÑоÑником дейÑÑÐ²Ð¸Ñ Ð¸ вÑеменно заблокиÑоваÑÑ Ð¾ÑÑалÑнÑÑ ÑÑÑаниÑÑ.',\n});
1\n\nexport const run = async ({ anchor, log, manager, own }) => {\n const instance = own(await manager.prepare('ModalPrompt', { details: 'ÐодалÑноÑÑÑ Ð·Ð°Ð´Ð°ÑÑÑÑ Ð¾ÑделÑно Ð¾Ñ ÑаÑÐ¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¾ÐºÐ½Ð°.' }));\n instance\n .setText('title', 'ÐÑивÑзаннÑй модалÑнÑй диалог')\n .setPresentation({ preset: 'anchored-dialog', modal: true, size: 'sm' })\n .setAnchor(anchor);\n await manager.open(instance);\n log('ÐÑкÑÑÑ Ð¼Ð¾Ð´Ð°Ð»ÑнÑй диалог Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸', instance.getState());\n};\n","./mmv2-r01-readiness.js":"export const recipe = Object.freeze({\n description: 'ÐÑовеÑÑеÑ, ÑÑо каÑалог подклÑÑÑн к гоÑÐ¾Ð²Ð¾Ð¼Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑÑ Ð¿Ð¾ клÑÑÑ globalThis.infotecs.ModalManagerV2 и не ÑоздаÑÑ ÐµÐ³Ð¾ копиÑ.',\n expected: [\n 'ÐлÑÑ globalThis.infotecs.ModalManagerV2 ÑказÑÐ²Ð°ÐµÑ Ð½Ð° ÑÐ¾Ñ Ð¶Ðµ обÑекÑ, коÑоÑÑй иÑполÑзÑÐµÑ ÐºÐ°Ñалог.',\n 'СÑаÑÑй Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ V1 оÑÑаÑÑÑÑ Ð´Ð¾ÑÑÑпен оÑделÑно по клÑÑÑ globalThis.infotecs.ModalManager.',\n 'getState() возвÑаÑÐ°ÐµÑ Ð½ÐµÐ¸Ð·Ð¼ÐµÐ½ÑемÑй Ñнимок: внеÑний код не Ð¼Ð¾Ð¶ÐµÑ Ð¿ÐµÑепиÑаÑÑ ÐµÐ³Ð¾ Ð¿Ð¾Ð»Ñ Ð¸Ð»Ð¸ ÑпиÑок ÑкземплÑÑов.',\n ],\n group: 'ÐодклÑÑение и API',\n id: 'MMV2-R01',\n safety: 'read-only',\n tags: ['ready', 'global', 'snapshot'],\n title: 'ÐÑовеÑиÑÑ Ð¿Ð¾Ð´ÐºÐ»ÑÑение к обÑÐµÐ¼Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑÑ',\n useWhen: 'ÐÑи добавлении новой ÑоÑки вÑ
ода, ÑÑÐ¾Ð±Ñ ÑбедиÑÑÑÑ: она ждÑÑ Ð·Ð°Ð¿ÑÑк пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸ иÑполÑзÑÐµÑ Ð¾Ð±Ñий менеджеÑ, а не ÑоздаÑÑ Ð²ÑоÑой.',\n});\n\nexport const run = async ({\n globalTarget,\n log,\n manager,\n namespaceKey,\n}) => {\n const readyManager = await manager.whenReady();\n const namespaceTarget = globalTarget[namespaceKey] ?? {};\n const state = manager.getState();\n\n log('ÐÑовеÑÐµÐ½Ñ Ð³Ð¾ÑовноÑÑÑ Ð¸ глобалÑнÑй клÑÑ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑа', {\n immutableInstances: Object.isFrozen(state.instances),\n immutableState: Object.isFrozen(state),\n legacyAvailable: Boolean(namespaceTarget.ModalManager),\n readyIdentity: readyManager === manager,\n v2GlobalIdentity: namespaceTarget.ModalManagerV2 === manager,\n });\n log('ТекÑÑий Ñнимок ÑоÑÑоÑÐ½Ð¸Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑа', state);\n};\n","./mmv2-r02-prepare-open.js":"export const recipe = Object.freeze({\n description: 'ÐоÑледоваÑелÑно вÑзÑÐ²Ð°ÐµÑ prepare(), наÑÑÑÐ°Ð¸Ð²Ð°ÐµÑ Ð¿Ð¾Ð´Ð³Ð¾ÑовленнÑй ÑкземплÑÑ ÑепоÑкой меÑодов и пеÑедаÑÑ ÐµÐ³Ð¾ в open().',\n expected: [\n 'ÐаждÑй меÑод наÑÑÑойки возвÑаÑÐ°ÐµÑ ÑÐ¾Ñ Ð¶Ðµ ModalInstance, поÑÑÐ¾Ð¼Ñ Ð²ÑÐ·Ð¾Ð²Ñ Ð¼Ð¾Ð¶Ð½Ð¾ обÑединÑÑÑ Ð² ÑепоÑкÑ.',\n 'open(instance) возвÑаÑÐ°ÐµÑ ÑÐ¾Ñ Ð¶Ðµ обÑÐµÐºÑ Ð¸ показÑÐ²Ð°ÐµÑ ÑооÑвеÑÑÑвÑÑÑее окно.',\n 'ÐоÑле закÑÑÑÐ¸Ñ ÑÑаÑÑÑ ÑкземплÑÑа ÑÑановиÑÑÑ closed; повÑоÑно иÑполÑзоваÑÑ Ð·Ð°Ð²ÐµÑÑÑннÑй ÑкземплÑÑ Ð½ÐµÐ»ÑзÑ.',\n ],\n group: 'ÐодклÑÑение и API',\n id: 'MMV2-R02',\n safety: 'read-only',\n tags: ['prepare', 'fluent', 'identity'],\n title: 'ÐодгоÑовиÑÑ, наÑÑÑоиÑÑ Ð¸ оÑкÑÑÑÑ Ð¾ÐºÐ½Ð¾',\n useWhen: 'Ðогда ÑодеÑжимое, кнопки и внеÑний вид окна нÑжно полноÑÑÑÑ Ð½Ð°ÑÑÑоиÑÑ Ð´Ð¾ пеÑвого показа полÑзоваÑелÑ.',\n});\n\nexport const run = async ({ log, manager, own }) => {\n const instance = own(await manager.prepare('ModalSuccess', {\n messages: ['ÐкземплÑÑ Ð¿Ð¾Ð´Ð³Ð¾Ñовлен до показа.'],\n }));\n const configured = instance\n .setText('title', 'MMV2-R02: подгоÑовленнÑй ÑкземплÑÑ')\n .setPresentation({ preset
1: 'dialog', size: 'sm' })\n .setAction({ id: 'close', role: 'primary', text: 'ÐакÑÑÑÑ ÐºÐµÐ¹Ñ' });\n const opened = await manager.open(instance);\n\n log('ÐÑовеÑено ÑоÑ
Ñанение одного ÑкземплÑÑа пÑи наÑÑÑойке и оÑкÑÑÑии', {\n fluentIdentity: configured === instance,\n instanceId: instance.instanceId,\n openIdentity: opened === instance,\n state: instance.getState(),\n });\n};\n","./mmv2-x01-html.js":"// dependencies: dompurify, vue\nimport DOMPurify from 'dompurify';\nimport {\n computed,\n defineComponent,\n h,\n markRaw,\n} from 'vue';\n\n// resources\nimport modalRecipeContentSource from '../modals/v2/ModalRecipeContent.vue?raw';\n\n\nconst MODAL_ID = 'ModalManagerV2CatalogApp/ModalRecipeContent';\nconst ALLOWED_TAGS = Object.freeze([\n 'code',\n 'em',\n 'li',\n 'ol',\n 'p',\n 'strong',\n 'ul',\n]);\n\nconst exampleHtml = `\n <p><strong>РазÑеÑÑÐ½Ð½Ð°Ñ ÑазмеÑка</strong> оÑÑаÑÑÑÑ Ð² окне.</p>\n <ul>\n <li>СпиÑки, <em>вÑделение</em> и <code>inline code</code>.</li>\n </ul>\n <img src=\"missing\" onerror=\"alert('xss')\">\n <a href=\"javascript:alert('xss')\">ÐпаÑÐ½Ð°Ñ ÑÑÑлка ÑÑановиÑÑÑ Ð¾Ð±ÑÑнÑм ÑекÑÑом.</a>\n`;\n\nexport const sanitizeRecipeHtml = value => DOMPurify.sanitize(value, {\n ALLOWED_ATTR: [],\n ALLOWED_TAGS,\n ALLOW_ARIA_ATTR: false,\n ALLOW_DATA_ATTR: false,\n});\n\nconst SafeHtmlContent = markRaw(defineComponent({\n name: 'RecipeSafeHtmlContent',\n props: {\n html: { type: String, default: '' },\n },\n setup: props => {\n const sanitizedHtml = computed(_ => sanitizeRecipeHtml(props.html));\n\n return _ => h('div', {\n 'data-test': 'mmv2-recipe-html-content',\n innerHTML: sanitizedHtml.value,\n });\n },\n}));\n\nexport const supportingSources = Object.freeze([\n Object.freeze({\n label: 'Vue-оболоÑка пÑоизволÑного ÑодеÑжимого',\n source: modalRecipeContentSource,\n }),\n]);\n\nexport const recipe = Object.freeze({\n description: 'ÐеÑедаÑÑ HTML-ÑÑÑÐ¾ÐºÑ Ð² Vue-компоненÑ, коÑоÑÑй оÑиÑÐ°ÐµÑ ÐµÑ Ð½ÐµÐ¿Ð¾ÑÑедÑÑвенно пеÑед HTML-sink Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ DOMPurify и ÑÑÑогого ÑпиÑка ÑазÑеÑÑннÑÑ
Ñегов.',\n expected: [\n 'ÐбзаÑ, ÑпиÑок, вÑделение и inline code оÑобÑажаÑÑÑÑ ÐºÐ°Ðº ÑазмеÑка.',\n 'img, обÑабоÑÑик onerror, ÑÑÑлка и javascript: URL не попадаÑÑ Ð² DOM; ÑекÑÑ ÑÑÑлки оÑÑаÑÑÑÑ ÑиÑаемÑм.',\n 'ÐÐµÐ½ÐµÐ´Ð¶ÐµÑ Ð¿Ð¾Ð»ÑÑÐ°ÐµÑ Ñже довеÑеннÑй Vue-компоненÑ; ÐºÐµÐ¹Ñ Ð½Ðµ ÑегиÑÑÑиÑÑÐµÑ runtime modal и не ÑоздаÑÑ Ð²ÑоÑой manager.',\n ],\n group: 'ÐÑоизволÑное ÑодеÑжимое',\n id: 'MMV2-X01',\n safety: 'read-only',\n tags: ['HTML', 'DOMPurify', 'XSS', 'allowlist'],\n title: 'ÐоказаÑÑ Ð¾ÑиÑенное HTML-ÑодеÑжимое',\n useWhen: 'ТолÑко когда бизнеÑ-ÑÑебование дейÑÑвиÑелÑно ÑÑебÑÐµÑ ÑазмеÑÐºÑ Ð¸Ð· ÑÑÑоки. ÐÐ»Ñ Ð¾Ð±ÑÑного ÑекÑÑа иÑполÑзÑйÑе инÑеÑполÑÑÐ¸Ñ Vue, а Ð´Ð»Ñ ÑÑÑÑкÑÑÑиÑованного инÑеÑÑейÑа â Vue-компоненÑ.',\n warnings: [\n 'v-html и innerHTML ÑвлÑÑÑÑÑ XSS-sink: авÑоÑизаÑÐ¸Ñ ÑÑÑаниÑÑ Ð¸ оÑÑÑÑÑÑвие Ñега script не делаÑÑ Ð½ÐµÐ¿ÑовеÑеннÑÑ ÑÑÑÐ¾ÐºÑ Ð±ÐµÐ·Ð¾Ð¿Ð°Ñной.',\n 'ÐÑиÑаÑÑ Ð½Ñжно Ñ Ñамого sink. ÐоÑле DOMPurify нелÑÐ·Ñ Ð´Ð¾Ð¿Ð¸ÑÑваÑÑ ÑазмеÑÐºÑ ÑÑÑоками или пеÑедаваÑÑ ÑезÑлÑÑÐ°Ñ ÐºÐ¾Ð´Ñ, коÑоÑÑй Ñнова менÑÐµÑ HTML.',\n 'Allowlist ÑÑого кейÑа намеÑенно не ÑазÑеÑÐ°ÐµÑ ÑÑÑлки, изобÑажениÑ, ÑÑили и лÑбÑе аÑÑибÑÑÑ; ÑаÑÑиÑение ÑпиÑка ÑÑебÑÐµÑ Ð¾ÑделÑного security review.',\n ],\n});\n\nexport const run = async ({ log, manager, own }) =>
1 {\n const instance = own(await manager.prepare(MODAL_ID, {\n contentComponent: SafeHtmlContent,\n contentProps: { html: exampleHtml },\n }));\n\n instance\n .setText('title', 'MMV2-X01: оÑиÑенное HTML-ÑодеÑжимое')\n .setPresentation({ size: 'sm' });\n\n await manager.open(instance);\n log('HTML пеÑедан в ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ñ Ð¾ÑиÑÑкой Ñ sink', {\n allowedTags: ALLOWED_TAGS,\n instanceId: instance.instanceId,\n });\n};\n","./mmv2-x02-js-configurator.js":"// dependencies: vue\nimport {\n defineComponent,\n h,\n markRaw,\n} from 'vue';\n\n// resources\nimport modalRecipeContentSource from '../modals/v2/ModalRecipeContent.vue?raw';\n\n\nconst MODAL_ID = 'ModalManagerV2CatalogApp/ModalRecipeContent';\n\nconst JsConfiguredContent = markRaw(defineComponent({\n name: 'RecipeJsConfiguredContent',\n props: {\n description: { type: String, default: '' },\n phase: { type: String, default: '' },\n },\n setup: props => _ => h('div', {\n 'data-test': 'mmv2-recipe-js-content',\n }, [\n h('p', [h('strong', 'СоÑÑоÑние: '), props.phase]),\n h('p', props.description),\n ]),\n}));\n\nexport const updateRecipeBody = (instance, contentProps) => instance\n .setText('title', 'MMV2-X02: Ñело изменено ÑеÑез public API')\n .setProps({ contentProps });\n\nexport const supportingSources = Object.freeze([\n Object.freeze({\n label: 'Vue-оболоÑка пÑоизволÑного ÑодеÑжимого',\n source: modalRecipeContentSource,\n }),\n]);\n\nexport const recipe = Object.freeze({\n description: 'ÐеÑедаÑÑ ModalInstance в обÑÑнÑÑ JS-ÑÑнкÑиÑ. ФÑнкÑÐ¸Ñ Ð¼ÐµÐ½ÑÐµÑ props вложенного компоненÑа ÑеÑез setProps() и заголовок ÑеÑез setText(), не полÑÑÐ°Ñ ÑÑÑÐ»ÐºÑ Ð½Ð° DOM.',\n expected: [\n 'Ðкно оÑкÑÑваеÑÑÑ Ñ Ð½Ð°ÑалÑнÑм ÑекÑÑом и ÑеÑез 700 Ð¼Ñ Ð¿Ð¾ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ Ð½Ð¾Ð²Ð¾Ðµ ÑоÑÑоÑние.',\n 'instanceId и локалÑнÑй Vue-ÑкземплÑÑ ÑоÑ
ÑанÑÑÑÑÑ: manager обновлÑÐµÑ props без remount.',\n 'ФÑнкÑÐ¸Ñ Ð¸ÑполÑзÑÐµÑ ÑолÑко пÑблиÑнÑй ModalInstance API; querySelector, innerHTML и ÑÑÑÐ½Ð°Ñ Ð·Ð°Ð¼ÐµÐ½Ð° DOM не нÑжнÑ.',\n ],\n group: 'ÐÑоизволÑное ÑодеÑжимое',\n id: 'MMV2-X02',\n safety: 'read-only',\n tags: ['JavaScript', 'setProps', 'setText', 'no DOM'],\n title: 'ÐзмениÑÑ Ñело JS-ÑÑнкÑией ÑеÑез API',\n useWhen: 'Ðогда даннÑе пÑиÑ
одÑÑ Ð¿Ð¾Ñле оÑкÑÑÑÐ¸Ñ Ð¾ÐºÐ½Ð° или обÑий configurator должен обновиÑÑ Ð¿ÑедÑÑавление, ÑоÑ
Ñанив lifecycle, ÑеакÑивноÑÑÑ Ð¸ локалÑное ÑоÑÑоÑние Vue-компоненÑа.',\n warnings: [\n 'ÐÑÑÐ¼Ð°Ñ Ð¿Ñавка DOM обÑ
Ð¾Ð´Ð¸Ñ Vue render tree, Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð·Ð°ÑÑÑÑа ÑледÑÑÑим render и ÑоздаÑÑ XSS-, focus- и cleanup-ÑиÑки.',\n 'ФÑнкÑÐ¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° полÑÑаÑÑ ModalInstance или пÑедмеÑнÑй callback, а не HTMLElement внÑÑÑенней повеÑÑ
ноÑÑи окна.',\n ],\n});\n\nexport const run = async ({ log, manager, own, wait }) => {\n const instance = own(await manager.prepare(MODAL_ID, {\n contentComponent: JsConfiguredContent,\n contentProps: {\n description: 'JS-конÑигÑÑаÑÐ¾Ñ ÐµÑÑ Ð½Ðµ пÑименил обновление.',\n phase: 'наÑалÑное',\n },\n }));\n\n instance\n .setText('title', 'MMV2-X02: иÑÑ
одное Ñело')\n .setPresentation({ size: 'sm' });\n\n await manager.open(instance);\n\n if (!await wait(700) || instance.status === 'closed') return;\n\n updateRecipeBody(instance, {\n description: 'ФÑнкÑÐ¸Ñ Ð²Ñзвала setProps({ contentProps }) Ñ Ñого же ModalInstance.',\n phase: 'обновлÑнное',\n });\n log('JS-ÑÑнкÑÐ¸Ñ Ð¾Ð±Ð½Ð¾Ð²Ð¸Ð»Ð° Ñело ÑеÑез ModalInstance API', instance.getState());\n};\n","./mmv2-x03-vue-component.js":"// dependencies: vue\nimport {\n defineComponent,\n h,\n markRaw,\n ref,\n} from 'vue';\n\n// components\nimport UiButton from '@ui/Button/index.vue';\n\n// resources\nimport modalRecipeContentSource from '../modals/v2/ModalRecipeContent.vue?raw';
1\n\n\nconst MODAL_ID = 'ModalManagerV2CatalogApp/ModalRecipeContent';\n\nconst VueContent = markRaw(defineComponent({\n name: 'RecipeVueContent',\n props: {\n label: { type: String, default: '' },\n },\n setup: props => {\n const count = ref(0);\n\n return _ => h('div', {\n 'data-test': 'mmv2-recipe-vue-content',\n }, [\n h('p', props.label),\n h('p', `ÐокалÑнÑй ÑÑÑÑÑик компоненÑа: ${count.value}`),\n h(UiButton, {\n attributes: { type: 'button' },\n buttonText: 'УвелиÑиÑÑ ÑÑÑÑÑик',\n onAction: _ => { count.value += 1; },\n type: 'secondary',\n }),\n ]);\n },\n}));\n\nexport const supportingSources = Object.freeze([\n Object.freeze({\n label: 'Vue-оболоÑка пÑоизволÑного ÑодеÑжимого',\n source: modalRecipeContentSource,\n }),\n]);\n\nexport const recipe = Object.freeze({\n description: 'ÐеÑедаÑÑ version-controlled Vue-ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ ÐºÐ°Ðº prop каÑаложной modal-оболоÑки. ÐÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ ÑодеÑÐ¶Ð¸Ñ ÑобÑÑвенное ÑоÑÑоÑние, обÑабоÑÑик ÑобÑÑÐ¸Ñ Ð¸ UiButton из дизайн-ÑиÑÑемÑ.',\n expected: [\n 'ÐнÑÑÑи окна оÑобÑажаеÑÑÑ Vue-ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð¸ кнопка из ui-list.',\n 'Ðаждое нажаÑие ÑвелиÑÐ¸Ð²Ð°ÐµÑ Ð»Ð¾ÐºÐ°Ð»ÑнÑй ref без обÑаÑÐµÐ½Ð¸Ñ Ðº manager и без remount окна.',\n 'ÐакÑÑÑие окна ÑниÑÑÐ¾Ð¶Ð°ÐµÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ñй Vue-ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð²Ð¼ÐµÑÑе Ñ ÐµÐ³Ð¾ локалÑнÑм ÑоÑÑоÑнием.',\n ],\n group: 'ÐÑоизволÑное ÑодеÑжимое',\n id: 'MMV2-X03',\n safety: 'read-only',\n tags: ['Vue', 'dynamic component', 'markRaw', 'UiButton'],\n title: 'ÐÑкÑÑÑÑ Ð¾ÐºÐ½Ð¾ Ñ Vue-компоненÑом',\n useWhen: 'Ðогда ÑÐµÐ»Ñ Ð¾ÐºÐ½Ð° нÑÐ¶Ð½Ñ ÑоÑмÑ, ÑеакÑивное ÑоÑÑоÑние, ÑобÑÑÐ¸Ñ Ð¸Ð»Ð¸ пеÑеиÑполÑзÑемÑе UI-компоненÑÑ. ÐÑо оÑновной пÑÑÑ Ð´Ð»Ñ Ñложного ÑодеÑжимого.',\n warnings: [\n 'Vue-ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ ÑвлÑеÑÑÑ Ð¸ÑполнÑемÑм кодом Ñ Ð¿Ð¾Ð»Ð½Ð¾Ð¼Ð¾ÑиÑми пÑиложениÑ: пеÑедаваÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ ÑолÑко довеÑеннÑй код из ÑбоÑки, а не Ñаблон или ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð¸Ð· оÑвеÑа API.',\n 'Modal host не подклÑÑÐ°ÐµÑ router, Pinia и дÑÑгие app plugins авÑомаÑиÑеÑки; завиÑимоÑÑи компоненÑа Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ ÑвнÑми.',\n ],\n});\n\nexport const run = async ({ log, manager, own }) => {\n const instance = own(await manager.prepare(MODAL_ID, {\n contentComponent: VueContent,\n contentProps: {\n label: 'ÐÑÐ¾Ñ Ð±Ð»Ð¾Ðº полноÑÑÑÑ Ð¾ÑÑиÑован пеÑеданнÑм Vue-компоненÑом.',\n },\n }));\n\n instance\n .setText('title', 'MMV2-X03: пÑоизволÑнÑй Vue-компоненÑ')\n .setPresentation({ size: 'sm' });\n\n await manager.open(instance);\n log('Vue-ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð¾ÑкÑÑÑ ÑеÑез convention-based modal ID', {\n instanceId: instance.instanceId,\n modalId: MODAL_ID,\n });\n};\n","./mmv2-x04-form-generator.js":"// classes\nimport { modalFlow } from '@classes/ModalManager/index.js';\n\n// resources\nimport formManagerSource from '@classes/FormManager/FormManager.js?raw';\nimport formInstanceSource from '@classes/FormManager/FormInstance.js?raw';\nimport formRuntimeSource from '@cmp/FormManager/FormRuntime.vue?raw';\nimport modalFormSource from '@cmp/CommonModals/ModalForm.vue?raw';\nimport formManagerModuleSource from '@/modules/form-manager/index.js?raw';\nimport formManagerRuntimeSource from '@/modules/form-manager/runtime.js?raw';\nimport newsletterSource from '@/modules/form-manager/forms/newsletter-subscription.js?raw';\n\n\nconst FORM_ID = 'Footer/NewsletterSubscription';\n\nexport const supportingSources = Object.freeze([\n Object.freeze({ label: 'ÐÑблиÑнÑй FormManager facade', source: formManagerSource }),\n Object.freeze({ label: 'Project wiring и lazy catalog', source: formManagerModuleSource }),\n Object.freeze({ label: 'ÐкземплÑÑ Ð¿Ð¾Ð´Ð³Ð¾Ñовленной ÑоÑмÑ', source: formInstanceSource }),\n Object.freeze({ label: 'DOM/ModalManagerV2 mount runtime', source: formManagerRuntimeSource }),\n Object.freeze({ label: 'ÐбÑий lifecycle FormGenerator', source: formRuntimeSource }),\n Object.freeze({ label: 'УнивеÑÑалÑÐ½Ð°Ñ Ð¾Ð±Ð¾Ð»Ð¾Ñка ModalForm', source: modalFormSource }),\n Object.freeze({ label: 'Factory ÑоÑÐ¼Ñ ÑаÑÑÑлки', source: newsletterSource }),\n]);\n\nexport const recipe = Object.freeze({\n description: 'ÐеÑÑÑ Ð¿ÑедопÑеделÑннÑÑ ÑоÑÐ¼Ñ ÑаÑÑÑлки из lazy catalog FormManager и оÑкÑÑÐ²Ð°ÐµÑ ÐµÑ ÑеÑез ÑнивеÑÑалÑнÑй ModalForm в presentation dialog-lg. Submit не обÑаÑаеÑÑÑ Ðº backend: payload возвÑаÑаеÑÑÑ ÐºÐ°Ðº result закÑÑÑого FormInstance.',\n expected: [\n 'Ð ÑиÑоком диалоге оÑобÑажаеÑÑÑ FormGenerator Ñ ÑемаÑиками, конÑакÑнÑми полÑми и ÑоглаÑиÑми ÑоÑÐ¼Ñ ÑаÑÑÑлки.',\n 'Ðнопка «ÐодпиÑаÑÑÑÑ» иÑполÑзÑÐµÑ client validation и busy lifecycle FormGenerator.',\n 'ÐоÑле submit окно закÑÑваеÑÑÑ, а жÑÑнал показÑÐ²Ð°ÐµÑ JSON-ÑовмеÑÑимÑй form payload без ÑеÑевого запÑоÑа.',\n 'Reset закÑÑÐ²Ð°ÐµÑ ÑолÑко пÑинадлежаÑий кейÑÑ FormInstance и ÑниÑÑÐ¾Ð¶Ð°ÐµÑ form store.',\n ],\n group: 'ÐÑоизволÑное ÑодеÑжимое',\n id: 'MMV2-X04',\n safety: 'read-only',\n tags: ['FormGenerator', 'FormManager', 'ModalForm', 'dialog-lg'],\n title: 'ÐÑкÑÑÑÑ ÑоÑÐ¼Ñ ÑаÑÑÑлки в dialog-lg',\n useWhen: 'Ðогда длинной ÑоÑме нÑжен ÑиÑокий диалог, а consumer должен вÑзваÑÑ ÐµÑ Ð¿Ð¾ ÑÑабилÑÐ½Ð¾Ð¼Ñ ID без ÑÑÑной ÑбоÑки ModalInstance и Vuex lifecycle.',\n warnings: [\n 'ModalForm â ÑнивеÑÑалÑнÑй modal adapter Ð´Ð»Ñ FormGenerator, а не оÑделÑнÑй renderer ÑоÑмÑ.',\n 'Factory ÑоздаÑÑ Ð½Ð¾Ð²Ñй dataForm Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ оÑкÑÑÑиÑ;
1 mutable runtime Ð¼ÐµÐ¶Ð´Ñ ÑеÑÑиÑми не пеÑеиÑполÑзÑеÑÑÑ.',\n 'ÐÑÐ¸Ð¼ÐµÑ Ð½Ð°Ð¼ÐµÑенно не вÑзÑÐ²Ð°ÐµÑ production transport ÑоÑÐ¼Ñ ÑаÑÑÑлки.',\n ],\n});\n\nexport const run = async ({\n globalTarget,\n log,\n namespaceKey,\n own,\n}) => {\n const FormManager = globalTarget[namespaceKey]?.FormManager;\n const modalManager = globalTarget[namespaceKey]?.ModalManagerV2;\n if (!FormManager) throw new Error('FormManager is not available');\n if (!modalManager) throw new Error('ModalManagerV2 is not available');\n\n const instance = own(await FormManager.open(FORM_ID, {}, {\n mount: modalManager,\n onSubmit: payload => {\n const result = payload?.sendData?.data ?? null;\n log('FormManager полÑÑил submit ÑоÑÐ¼Ñ ÑаÑÑÑлки', result);\n return modalFlow.close(result);\n },\n presentation: { preset: 'dialog-lg' },\n }));\n log('ФоÑма ÑаÑÑÑлки оÑкÑÑÑа ÑеÑез ModalForm', {\n formId: FORM_ID,\n instanceId: instance.instanceId,\n modalId: instance.mountResult.id,\n preset: 'dialog-lg',\n });\n};\n\nexport default recipe;\n","./mmv2-x05-callback-form.js":"// classes\nimport { modalFlow } from '@classes/ModalManager/index.js';\n\n// resources\nimport callbackSource from '@/modules/form-manager/forms/callback-request.js?raw';\nimport modalFormSource from '@cmp/CommonModals/ModalForm.vue?raw';\n\n\nconst FORM_ID = 'Footer/CallbackRequest';\n\nexport const supportingSources = Object.freeze([\n Object.freeze({ label: 'Factory ÑоÑÐ¼Ñ Ð¾Ð±ÑаÑного звонка', source: callbackSource }),\n Object.freeze({ label: 'УнивеÑÑалÑÐ½Ð°Ñ Ð¾Ð±Ð¾Ð»Ð¾Ñка ModalForm', source: modalFormSource }),\n]);\n\nexport const recipe = Object.freeze({\n description: 'ÐÑкÑÑÐ²Ð°ÐµÑ Ð¿ÑедопÑеделÑннÑÑ ÑоÑÐ¼Ñ Ð¾Ð±ÑаÑного звонка ÑеÑез ÑÐ¾Ñ Ð¶Ðµ ModalForm, но менÑÐµÑ presentation на боковой sheet. Так ÑоÑма и ÐµÑ lifecycle оÑÑаÑÑÑÑ Ð¿Ñежними, а ÑпоÑоб показа задаÑÑ options ÑекÑÑего вÑзова FormManager.',\n expected: [\n 'СпÑава оÑкÑÑваеÑÑÑ sheet Ñ Ð¿Ð¾Ð»Ñми имени, ÑелеÑона и двÑÐ¼Ñ ÑоглаÑиÑми.',\n 'ФоÑма иÑполÑзÑÐµÑ ÑÑ Ð¶Ðµ universal ModalForm, ÑÑо и ÐºÐµÐ¹Ñ ÑаÑÑÑлки; оÑлиÑаеÑÑÑ ÑолÑко presentation.',\n 'Submit пÑоÑ
Ð¾Ð´Ð¸Ñ client validation, не вÑзÑÐ²Ð°ÐµÑ backend и закÑÑÐ²Ð°ÐµÑ FormInstance Ñ payload в result.',\n ],\n group: 'ÐÑоизволÑное ÑодеÑжимое',\n id: 'MMV2-X05',\n safety: 'read-only',\n tags: ['FormGenerator', 'FormManager', 'ModalForm', 'sheet'],\n title: 'ÐÑкÑÑÑÑ ÑоÑÐ¼Ñ Ð·Ð²Ð¾Ð½ÐºÐ° в sheet',\n useWhen: 'Ðогда компакÑнÑÑ ÑоÑÐ¼Ñ Ð½Ñжно показаÑÑ ÑÐ±Ð¾ÐºÑ Ð¸ ÑоÑ
ÑаниÑÑ ÐµÐ´Ð¸Ð½Ñй API open/closed незавиÑимо Ð¾Ñ presentation ModalManagerV2.',\n warnings: [\n 'Presentation не должен попадаÑÑ Ð²Ð½ÑÑÑÑ FormGenerator-ÑÑ
емÑ: его пÑименÑÐµÑ modal adapter FormManager.',\n 'ÐÑÐ¸Ð¼ÐµÑ Ð½Ð°Ð¼ÐµÑенно не вÑзÑÐ²Ð°ÐµÑ production transport ÑоÑÐ¼Ñ Ð¾Ð±ÑаÑного звонка.',\n ],\n});\n\nexport const run = async ({\n globalTarget,\n log,\n namespaceKey,\n own,\n}) => {\n const FormManager = globalTarget[namespaceKey]?.FormManager;\n const modalManager = globalTarget[namespaceKey]?.ModalManagerV2;\n if (!FormManager) throw new Error('FormManager is not available');\n if (!modalManager) throw new Error('ModalManagerV2 is not available');\n\n const instance = own(await FormManager.open(FORM_ID, {}, {\n mount: modalManager,\n onSubmit: payload => {\n const result = payload?.sendData?.data ?? null;\n log('FormManager полÑÑил submit ÑоÑÐ¼Ñ Ð¾Ð±ÑаÑного звонка', result);\n return modalFlow.close(result);\n },\n presentation: { preset: 'sheet', side: 'right' },\n }));\n log('ФоÑма обÑаÑного звонка оÑкÑÑÑа ÑеÑез ModalForm', {\n formId: FORM_ID,\n instanceId: instance.instanceId,\n modalId: instance.mountResult.id,\n preset: 'sheet',\n });\n};\n\nexport default recipe;\n"}),cn=Object.freeze(Object.entries(sn).map(([e,n])=>((e,n)=>{const t=n.recipe,a=n.supportingSources??[];if(!/^MMV2-[A-Z]\d{2}$/.test(t?.id??""))throw new TypeError(`Recipe "${e}" must have a stable MMV2 ID`);if(!rn.includes(t.group))throw new TypeError(`Recipe "${t.id}" has an unknown group`);if(!Object.values(on).includes(t.safety))throw new TypeError(`Recipe "${t.id}" has an unknown safety profile`);if(!Array.isArray(t.expected)||0===t.expected.length)throw new TypeError(`Recipe "${t.id}" must describe expected results`);
1if("function"!=typeof n.run)throw new TypeError(`Recipe "${t.id}" must export run()`);if(!Array.isArray(t.warnings??[])||!Array.isArray(a)||a.some(e=>"string"!=typeof e?.label||"string"!=typeof e?.source))throw new TypeError(`Recipe "${t.id}" has invalid supporting content`);const r=ln[e],o=[{label:"Ðод запÑÑка кейÑа",source:r},...a].map(e=>Object.freeze({...e}));return Object.freeze({...t,expected:Object.freeze([...t.expected]),run:n.run,source:r,sources:Object.freeze(o),tags:Object.freeze([...t.tags??[]]),warnings:Object.freeze([...t.warnings??[]])})})(e,n)).sort((e,n)=>rn.indexOf(e.group)-rn.indexOf(n.group)||e.id.localeCompare(n.id))),dn=["aria-live","role"],un=["href"],mn=["id"],pn=["href"],gn=["aria-label"],fn=["innerHTML"],Mn=["innerHTML"],bn=["id"],yn=["href"],hn="b-button b-button--secondary",vn={__name:"index",props:{manager:l(Object,null),managerError:l(Object,null),root:l(Object,null,!0)},setup(e){const n=e,{$b:t}=s("modal-manager-v2-catalog"),a={iconAlign:"left",loaderAlign:"right",size:"",type:"primary"},r=o(""),l=o({query:"",selected:{},count:0}),z=o(!1),D=o(!1),L=o(!1),G=o([]),$=o(n.manager?.getState()??null),U=o(""),B=o(""),W=o("");let q=null,H=null;const X=rn.filter(e=>cn.some(n=>n.group===e)),J=X.map(e=>({group:e,recipes:cn.filter(n=>n.group===e)})),K=c(e=>({id:"modal-product-filters",name:"ФилÑÑÑÑ",count:l.value.count||null,active:l.value.count>0})),Y={content:t`,readiness-content`,root:t`,readiness`,summary:`${t`,readiness-summary`} ${hn}`},Z={tooltipClose:"РазвеÑнÑÑÑ Ð¿Ð¾ÑÑнение о гоÑовноÑÑи и ÑоÑÑоÑнии менеджеÑа",tooltipOpen:"СвеÑнÑÑÑ Ð¿Ð¾ÑÑнение о гоÑовноÑÑи и ÑоÑÑоÑнии менеджеÑа"},Q={content:t`,source-content`,root:t`,source`,summary:`${t`,summary`} ${hn}`},ee={tooltipClose:"РазвеÑнÑÑÑ Ð¸ÑÑ
однÑй код кейÑа",tooltipOpen:"СвеÑнÑÑÑ Ð¸ÑÑ
однÑй код кейÑа"},ne={content:t`,toc-content`,root:t`,toc`,summary:`${t`,toc-summary`} ${hn}`},te={tooltipClose:"РазвеÑнÑÑÑ ÑодеÑжание кейÑов",tooltipOpen:"СвеÑнÑÑÑ ÑодеÑжание кейÑов"},ae=e=>e.code,re={attributes:{autocomplete:"off",placeholder:"ID, название, Ñег"},id:"mmv2-recipe-search",texts:{label:"ÐоиÑк по кейÑам"},type:"search"},oe={options:[{code:"",id:"all",label:"ÐÑе гÑÑппÑ"},...X.map((e,n)=>({code:e,id:`group-${n}`,label:e}))],texts:{label:"ÐÑÑппа",notFound:"ÐÑÑппа не найдена",placeholder:"ÐÑе гÑÑппÑ"}},se={options:[{code:"",id:"all",label:"ÐÑбое влиÑние"},{code:"read-only",id:"read-only",label:"Ðез изменений даннÑÑ
"},{code:"local-side-effect",id:"local-side-effect",label:"ÐокалÑное дейÑÑвие в бÑаÑзеÑе"}],texts:{label:"ÐлиÑние кейÑа",notFound:"ÐаÑÐ¸Ð°Ð½Ñ Ð²Ð»Ð¸ÑÐ½Ð¸Ñ Ð½Ðµ найден",placeholder:"ÐÑбое влиÑние"}},ie=c(e=>n.managerError?`ÐаÑалог не Ð¼Ð¾Ð¶ÐµÑ Ð·Ð°Ð¿ÑÑкаÑÑ ÐºÐµÐ¹ÑÑ. Ðод оÑибки: ${n.managerError.code??"ERROR"}. ТеÑ
ниÑеÑкое ÑообÑение: ${n.managerError.message}`:""),le=c(e=>{const n=U.value.trim().toLocaleLowerCase("ru");return cn.filter(e=>{const t=[e.id,e.title,e.description,e.useWhen,...e.tags].join(" ").toLocaleLowerCase("ru");return(!n||t.includes(n))&&(!B.value||e.group===B.value)&&(!W.value||e.safety===W.value)})}),ce=e=>{try{return JSON.stringify(e,null,2)}catch{return String(e)}},de=c(e=>G.value.length?G.value.map(e=>{const n=null===e.data?"":`\n${ce(e.data)}`;return`[${e.time}] ${e.level.toUpperCase()} ${e.message}${n}`}).join("\n\n"):"ÐÑÑнал пока пÑÑÑ."),ue=(e,n="blue")=>({classes:{root:t`,badge`},texts:{text:e},type:n}),me=e=>{G.value.push({...e,time:(new Date).toLocaleTimeString("ru-RU")})},pe=async({preserveFilters:e=!1}={})=>{if(e||(l.value={query:"",selected:{},count:0}),q){D.value=!0;try{await q.reset(),me({data:null,level:"info",message:"ÐÐµÐ¹Ñ ÑбÑоÑен"})}finally{q=null,z.value=!1,D.value=!1}}},ge=async(e,t)=>{const a=t?.event?.currentTarget;await pe({preserveFilters:"MMV2-C05"===e.id}),r.value=e.id,G.value=[],L.value=!0,location.hash=e.id.toLowerCase(),q=(({eventTarget:e=globalThis.document??null,globalTarget:n=globalThis,manager:t,namespaceKey:a="infotecs",onLog:r=e=>null})=>{const o=[],s=new AbortController,i=new Set;let l=null;const c=(e,n=null,t="info")=>{r({data:n,level:t,message:e})},d=e=>(o.push(e),n=>{const t=o.indexOf(e);return-1!==t&&(o.splice(t,1),!0)});return{context:{createLocalObjectUrl:e=>{const t=n.URL.createObjectURL(e);let a=!0;const r=e=>!!a&&(a=!1,n.URL.revokeObjectURL(t),!0);return d(r),{revoke:r,url:t}},eventTarget:e,globalTarget:n,log:c,manager:t,namespaceKey:a,own:e=>(i.add(e),Promise.resolve(e.closed).then(n=>{i.delete(e),c(`ÐкземплÑÑ ${e.instanceId} закÑÑÑ`,n)},n=>{i.delete(e),c(`ÐÑибка closed Ñ ${e.instanceId}`,N(n),"error")}),e),registerCleanup:d,signal:s.signal,wait:e=>((e,n)=>new Promise(t=>{if(n.aborted)return void t(!1);const a=e=>{clearTimeout(r),t(!1)},r=setTimeout(e=>{n.removeEventListener("abort",a),t(!0)},e);n.addEventListener("abort",a,{once:!0})}))(e,s.signal)},reset:e=>l||(l=(async()=>{s.abort();const e=[...i].reverse();for(const t of e)if("closed"!==t.status)try{await t.close({recipeReset:!0})}catch(n){c(`Ðе ÑдалоÑÑ Ð·Ð°ÐºÑÑÑÑ ${t.instanceId}`,N(n),"error")}i.clear();for(const t of[...o].reverse())try{await t()}catch(n){c("ÐÑибка cleanup кейÑа",N(n),"error")}o.length=0})(),l)}})({manager:n.manager,namespaceKey:x,onLog:me}),z.value=!0;try{me({data:null,level:"info",message:`ÐапÑÑк ${e.id}`}),await e.run({...q.context,anchor:a,appliedFilters:l.value,onFiltersApplied:e=>l.value=e}),me({data:null,level:"info",message:`${e.id} запÑÑен`})}catch(o){me({data:{code:o?.code??null,message:o?.message??String(o)},level:"error",message:`${e.id} завеÑÑилÑÑ Ð¾Ñибкой`})}finally{L.value=!1}};return d(async e=>{n.manager&&(H=n.manager.subscribe(e=>{$.value=e})),await u();const t=location.hash.slice(1).toUpperCase(),a=cn.find(e=>e.id===t);a&&document.getElementById(a.id.toLowerCase())?.scrollIntoView()}),m(e=>{H?.(),q?.reset()}),(n,o)=>(p(),g(h,null,[f("header",{class:M(b(t)`,header`)},[f("p",{class:M(b(t)`,eyebrow`)},"ÐнÑÑÑÑменÑÑ Ð¸Ð½ÑеÑÑейÑа",2),f("h1",{class:M(b(t)`,title`)},"ModalManagerV2",2),f("p",{class:M(b(t)`,lead`)}," ModalManagerV2 â ÑеÑÐ²Ð¸Ñ ÑÑонÑенда, коÑоÑÑй ÑоздаÑÑ, наÑÑÑаиваеÑ, показÑÐ²Ð°ÐµÑ Ð¸ закÑÑÐ²Ð°ÐµÑ Ð¼Ð¾Ð´Ð°Ð»ÑнÑе окна. Ðа ÑÑой ÑÑÑаниÑе «кейÑ» â неболÑÑой иÑполнÑемÑй пÑимеÑ: он обÑÑÑнÑÐµÑ Ð·Ð°Ð´Ð°ÑÑ, запÑÑÐºÐ°ÐµÑ Ð¿ÑблиÑнÑй API и показÑÐ²Ð°ÐµÑ Ð¾Ð¶Ð¸Ð´Ð°ÐµÐ¼Ñй ÑезÑлÑÑаÑ, жÑÑнал вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸ иÑÑ
однÑй код. ",2)],2),f("section",{"aria-live":e.managerError?"assertive":"polite",class:M([b(t)`,status`,e.managerError&&b(t)`,status,error`]),role:e.managerError?"alert":"status"},[f("h2",{class:M(b(t)`,status-title`)},y(e.managerError?"ModalManagerV2 недоÑÑÑпен":"ModalManagerV2 гоÑов к запÑÑÐºÑ ÐºÐµÐ¹Ñов"),3),e.managerError?(p(),g("p",{key:0,class:M(b(t)`,status-text`)},y(ie.value),3)):(p(),g(h,{key:1},[f("p",{class:M(b(t)`,status-text`)},[...o[5]||(o[5]=[v(" ÐбÑий ÑкземплÑÑ Ð´Ð¾ÑÑÑпен по клÑÑÑ ",-1),f("code",null,"globalThis.infotecs.ModalManagerV2",-1),v(". ÐаÑалог дождалÑÑ Ð·Ð°Ð²ÐµÑÑÐµÐ½Ð¸Ñ ",-1),f("code",null,"whenReady()",-1),v(" и Ð¼Ð¾Ð¶ÐµÑ Ð·Ð°Ð¿ÑÑкаÑÑ ÐºÐµÐ¹ÑÑ. ",-1)])],2),w(C,{classes:Y,"is-opened":!1,"is-use-slot":!0,texts:Z},{summary:O(()=>[...o[6]||(o[6]=[f("span",null,"ÐодÑобнее о гоÑовноÑÑи и ÑоÑÑоÑнии",-1)])]),content:O(()=>[f("p",{class:M(b(t)`,status-text`)},[...o[7]||(o[7]=[f("code",null,"globalThis",-1),v(" â глобаÐ
1»ÑнÑй обÑÐµÐºÑ ÑекÑÑей ÑÑÑаниÑÑ, ",-1),f("code",null,"infotecs",-1),v(" â пÑоÑÑÑанÑÑво имÑн (namespace) ÑÑонÑенда пÑоекÑа, а ",-1),f("code",null,"ModalManagerV2",-1),v(" â ÑвойÑÑво Ñ ÑкземплÑÑом менеджеÑа. Namespace ÑобиÑÐ°ÐµÑ Ð¿ÑблиÑнÑе обÑекÑÑ Ð¿ÑоекÑа под одним глобалÑнÑм клÑÑом, вмеÑÑо Ñого ÑÑÐ¾Ð±Ñ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÑÑ ÐºÐ°Ð¶Ð´Ñй обÑÐµÐºÑ Ð¾ÑделÑно в ",-1),f("code",null,"globalThis",-1),v(". ",-1)])],2),f("p",{class:M(b(t)`,status-text`)},[...o[8]||(o[8]=[v(" УÑпеÑное завеÑÑение ",-1),f("code",null,"whenReady()",-1),v(" ознаÑаеÑ, ÑÑо ÑлÑжебнÑй ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð´Ð»Ñ Ð¼Ð¾Ð½ÑиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¾ÐºÐ¾Ð½ в DOM (в API он назÑваеÑÑÑ ",-1),f("code",null,"host",-1),v(") иниÑиализиÑован и Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑинимаÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ. «ÐоÑов» не ознаÑаеÑ, ÑÑо какое-либо окно Ñже оÑкÑÑÑо. ТекÑÑий Ñнимок показÑваеÑÑÑ Ð²Ð¾Ð·Ð»Ðµ запÑÑенного кейÑа, а наблÑдаемÑе пеÑеÑ
Ð¾Ð´Ñ Ð¾ÑÑаÑÑÑÑ Ð² его жÑÑнале. ÐейÑÑ Ð¸ÑполÑзÑÑÑ Ð¾Ð±Ñий ÑкземплÑÑ â оÑделÑнÑй Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ Ð´Ð»Ñ ÑÑÑаниÑÑ Ð½Ðµ ÑоздаÑÑÑÑ. ",-1)])],2),f("h3",{class:M(b(t)`,state-definitions-title`)},"ÐÐ¾Ð»Ñ Ñнимка ÑоÑÑоÑниÑ",2),f("dl",{class:M(b(t)`,state-definitions`)},[f("div",{class:M(b(t)`,state-definition`)},[...o[9]||(o[9]=[f("dt",null,[f("code",null,"revision")],-1),f("dd",null," УвелиÑиваеÑÑÑ Ð¿Ñи каждом заÑикÑиÑованном изменении менеджеÑа и показÑваеÑ, поÑвилÑÑ Ð»Ð¸ новÑй Ñнимок. ",-1)])],2),f("div",{class:M(b(t)`,state-definition`)},[...o[10]||(o[10]=[f("dt",null,[f("code",null,"openCount")],-1),f("dd",null," ÐолиÑеÑÑво ÑкземплÑÑов в ÑÑеке показа, вклÑÑÐ°Ñ Ð²ÐµÑÑ
нее окно и пеÑекÑÑÑÑе им нижние окна. ",-1)])],2),f("div",{class:M(b(t)`,state-definition`)},[...o[11]||(o[11]=[f("dt",null,[f("code",null,"liveCount")],-1),f("dd",null," ÐолиÑеÑÑво ÑозданнÑÑ
ÑкземплÑÑов, коÑоÑÑе еÑÑ Ð½Ðµ бÑли полноÑÑÑÑ Ð·Ð°ÐºÑÑÑÑ: подгоÑовленнÑÑ
к Ð¿Ð¾ÐºÐ°Ð·Ñ Ð¸ наÑ
одÑÑиÑ
ÑÑ Ð² ÑÑеке. ",-1)])],2),f("div",{class:M(b(t)`,state-definition`)},[...o[12]||(o[12]=[f("dt",null,[f("code",null,"activeModalId")],-1),f("dd",null,[v(" ID веÑÑ
него окна, Ñ ÐºÐ¾ÑоÑÑм взаимодейÑÑвÑÐµÑ Ð¿Ð¾Ð»ÑзоваÑелÑ; "),f("code",null,"null"),v(" ознаÑаеÑ, ÑÑо ÑÑек показа пÑÑÑ. ")],-1)])],2)],2)]),_:1})],64))],10,dn),f("section",{class:M(b(t)`,guide`),"aria-labelledby":"mmv2-guide-title"},[f("h2",{id:"mmv2-guide-title",class:M(b(t)`,guide-title`)},"Ðак полÑзоваÑÑÑÑ ÐºÐ°Ñалогом",2),f("ol",{class:M(b(t)`,guide-list`)},[...o[13]||(o[13]=[f("li",null,"ÐÑбеÑиÑе ÐºÐµÐ¹Ñ Ð¸ пÑоÑиÑайÑе, Ð´Ð»Ñ ÐºÐ°ÐºÐ¾Ð¹ задаÑи он подÑ
одиÑ.",-1),f("li",null,"СвеÑÑÑе Ñаздел «ЧÑо должно пÑоизойÑи» и нажмиÑе «ÐапÑÑÑиÑÑ ÐºÐµÐ¹Ñ».",-1),f("li",null,"ÐÑполниÑе дейÑÑвие в оÑкÑÑвÑемÑÑ Ð¾ÐºÐ½Ðµ и ÑÑавниÑе жÑÑнал Ñ ÑекÑÑим ÑоÑÑоÑнием менеджеÑа.",-1),f("li",null,"ÐакÑойÑе окно и нажмиÑе «СбÑоÑиÑÑ ÐºÐµÐ¹Ñ», ÑÑÐ¾Ð±Ñ Ð¾ÑвободиÑÑ ÑозданнÑе им локалÑнÑе ÑеÑÑÑÑÑ.",-1)])],2),f("p",{class:M(b(t)`,guide-note`)}," ÐеÑка «без изменений даннÑÑ
» ознаÑаеÑ, ÑÑо ÐºÐµÐ¹Ñ Ð½Ðµ менÑÐµÑ ÑеÑвеÑнÑе даннÑе. «ÐокалÑное дейÑÑвие в бÑаÑзеÑе» можеÑ, напÑимеÑ, ÑоздаÑÑ Ð²ÑеменнÑй Ñайл или запÑÑÑиÑÑ ÐµÐ³Ð¾ загÑÑзкÑ, но Ñакже не оÑпÑавлÑÐµÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½Ð° ÑеÑвеÑ. ",2),f("p",{class:M(b(t)`,guide-note`)}," ÐезопаÑноÑÑÑ ÑодеÑжимого оÑениваеÑÑÑ Ð¾ÑделÑно Ð¾Ñ Ð²Ð»Ð¸ÑÐ½Ð¸Ñ Ð½Ð° даннÑе. ÐÑедÑпÑеждение в каÑÑоÑке ознаÑаеÑ, ÑÑо ÐºÐµÐ¹Ñ Ð¸Ð¼ÐµÐµÑ Ð¾Ð±ÑзаÑелÑнÑÑ Ð³ÑаниÑÑ Ð´Ð¾Ð²ÐµÑиÑ: напÑимеÑ, HTML ÑÑебÑÐµÑ Ð¾ÑиÑÑки, а Vue-ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ â довеÑенного version-controlled кода. ",2),w(C,{classes:ne,"is-opened":!1,"is-use-slot":!0,texts:te},{summary:O(()=>[f("span",{class:M(b(t)`,toc-heading`)},[o[14]||(o[14]=f("span",null,"СодеÑжание кейÑов",-1)),f("span",{class:M(b(t)`,toc-count`)},"ÐÑего: "+y(b(cn).length),3)],2)]),content:O(()=>[f("nav",{class:M(b(t)`,toc-nav`),"aria-label":"СодеÑжание кейÑов"},[f("ul",{class:M(b(t)`,toc-groups`)},[(p(!0),g(h,null,F(b(J),e=>(p(),g("li",{key:e.group,class:M(b(t)`,toc-group`)},[f("h3",{class:M(b(t)`,toc-group-title`)},y(e.group),3),f("ul",{class:M(b(t)`,toc-list`)},[(p(!0),g(h,null,F(e.recipes,e=>(p(),g("li",{key:e.id},[f("a",{class:M(b(t)`,toc-link`),href:`#${e.id.toLowerCase()}`},[f("span",{class:M(b(t)`,toc-id`)}
1,y(e.id),3),f("span",null,y(e.title),1)],10,un)]))),128))],2)],2))),128))],2)],2)]),_:1})],2),f("form",{class:M(b(t)`,filters`),role:"search",onSubmit:o[3]||(o[3]=S(()=>{},["prevent"]))},[w(T,{modelValue:U.value,"onUpdate:modelValue":o[0]||(o[0]=e=>U.value=e),params:re},null,8,["modelValue"]),w(P,{modelValue:B.value,"onUpdate:modelValue":o[1]||(o[1]=e=>B.value=e),params:oe,reduce:ae},null,8,["modelValue"]),w(P,{modelValue:W.value,"onUpdate:modelValue":o[2]||(o[2]=e=>W.value=e),params:se,reduce:ae},null,8,["modelValue"])],34),f("section",{"aria-label":"ÐейÑÑ ModalManagerV2",class:M(b(t)`,recipe-list`)},[(p(!0),g(h,null,F(le.value,n=>{return p(),g("article",{id:n.id.toLowerCase(),key:n.id,class:M([b(t)`,recipe`,r.value===n.id&&b(t)`,recipe,active`])},[f("div",{class:M(b(t)`,recipe-heading`)},[f("h2",{class:M(b(t)`,recipe-title`)},[f("a",{class:M(b(t)`,recipe-link`),href:`#${n.id.toLowerCase()}`},y(n.id)+" â "+y(n.title),11,pn)],2)],2),f("div",{class:M(b(t)`,badges`)},[w(_,{params:ue(n.group)},null,8,["params"]),w(_,{params:ue((s=n.safety,"read-only"===s?"без изменений даннÑÑ
":"локалÑное дейÑÑвие в бÑаÑзеÑе"),"local-side-effect"===n.safety?"red":"blue")},null,8,["params"]),(p(!0),g(h,null,F(n.tags,e=>(p(),j(_,{key:e,params:ue(e)},null,8,["params"]))),128))],2),f("p",{class:M(b(t)`,recipe-text`)},y(n.description),3),f("p",{class:M(b(t)`,recipe-usage`)},[o[15]||(o[15]=f("strong",null,"Ðогда иÑполÑзоваÑÑ:",-1)),v(" "+y(n.useWhen),1)],2),n.warnings.length?(p(),g("aside",{key:0,class:M(b(t)`,warning`)},[o[16]||(o[16]=f("strong",null,"ÐгÑаниÑÐµÐ½Ð¸Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑÑи и аÑÑ
иÑекÑÑÑÑ:",-1)),f("ul",{class:M(b(t)`,warning-list`)},[(p(!0),g(h,null,F(n.warnings,e=>(p(),g("li",{key:e},y(e),1))),128))],2)],2)):I("",!0),f("p",{class:M(b(t)`,expected-title`)},[...o[17]||(o[17]=[f("strong",null,"ЧÑо должно пÑоизойÑи:",-1)])],2),f("ul",{class:M(b(t)`,expected`)},[(p(!0),g(h,null,F(n.expected,e=>(p(),g("li",{key:e},y(e),1))),128))],2),f("div",{class:M(b(t)`,actions`)},["chip"===n.trigger?(p(),j(A,{key:0,params:{...K.value,disabled:Boolean(e.managerError)||L.value},onClick:e=>ge(n)},null,8,["params","onClick"])):(p(),j(i,R({key:1,ref_for:!0},a,{"aria-busy":L.value&&r.value===n.id,"button-text":L.value&&r.value===n.id?"ÐÐµÐ¹Ñ Ð²ÑполнÑеÑÑÑâ¦":"ÐапÑÑÑиÑÑ ÐºÐµÐ¹Ñ",disabled:Boolean(e.managerError)||L.value,onAction:e=>ge(n,e)}),null,16,["aria-busy","button-text","disabled","onAction"])),w(i,R({ref_for:!0},a,{"button-text":D.value&&r.value===n.id?"ÐÐµÐ¹Ñ ÑбÑаÑÑваеÑÑÑâ¦":"СбÑоÑиÑÑ ÐºÐµÐ¹Ñ",disabled:r.value!==n.id||!z.value||D.value,type:"secondary",onAction:o[4]||(o[4]=e=>pe())}),null,16,["button-text","disabled"])],2),r.value===n.id?(p(),g("section",{key:1,"aria-label":`РезÑлÑÑÐ°Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ ${n.id}`,class:M(b(t)`,runtime`)},[f("h3",{class:M(b(t)`,panel-title`)},"ЧÑо пÑоизоÑло поÑле запÑÑка",2),f("div",{class:M(b(t)`,runtime-grid`)},[f("section",null,[f("h4",{class:M(b(t)`,panel-subtitle`)},"ÐÑÑнал Ñагов кейÑа",2),f("pre",{class:M(b(t)`,log`),"aria-live":"polite"},y(de.value),3)]),f("section",null,[f("h4",{class:M(b(t)`,panel-subtitle`)},"ТекÑÑий Ñнимок ÑоÑÑоÑÐ½Ð¸Ñ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑа",2),f("pre",{class:M(b(t)`,state`)},[f("code",{class:"hljs language-json",innerHTML:b(E)(ce($.value),"json")},null,8,fn)],2)])],2)],10,gn)):I("",!0),w(C,{classes:Q,"is-opened":!1,"is-use-slot":!0,texts:ee},{summary:O(()=>[...o[18]||(o[18]=[f("span",null,"ÐÑÑ
однÑй код кейÑа",-1)])]),content:O(()=>[(p(!0),g(h,null,F(n.sources,e=>(p(),g("section",{key:e.label,class:M(b(t)`,source-entry`)},[f("h4",{class:M(b(t)`,source-title`)},y(e.label),3),f("pre",{class:M(b(t)`,code`)},[f("code",{class:M(`hljs language-${b(V)(e.source)}`),innerHTML:b(E)(e.source,b(V)(e.source))},null,10,Mn)],2)],2))),128))]),_:2},1024)],10,mn);var s}),128)),0===le.value.length?(p(),g("p",{key:0,class:M(b(t)`,empty`)}," Ðо заданнÑм ÑилÑÑÑам кейÑÑ Ð½Ðµ найденÑ. ",2)):I("",!0)],2),f("section",{class:M(b(t)`,automated`),"aria-labelledby":"mmv2-automated-title"},[f("h2",{id:"mmv2-automated-title",class:M(b(t)`,automated-title`)}," СÑенаÑии ÑолÑко Ð´Ð»Ñ Ð°Ð²ÑомаÑизиÑованной пÑовеÑки ",2),f("p",{class:M(b(t)`,automated-text`)}," У ÑÑиÑ
каÑÑоÑек Ð½ÐµÑ ÐºÐ½Ð¾Ð¿ÐºÐ¸ запÑÑка: ÑÑенаÑии ÑниÑÑожаÑÑ Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ, пеÑедаÑÑ Ð·Ð°Ð²ÐµÐ´Ð¾Ð¼Ð¾ оÑибоÑнÑе даннÑе или воÑпÑоизводÑÑ Ð³Ð¾Ð½ÐºÐ¸ аÑинÑ
ÑоннÑÑ
опеÑаÑий. Ðни вÑполнÑÑÑÑÑ ÑеÑÑовÑм ÑаннеÑом на оÑделÑном изолиÑованном ÑкземплÑÑе и никогда не иÑполÑзÑÑÑ Ð¾Ð±Ñий Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ ÑÑой ÑÑÑаниÑÑ. ",2),f("div",{class:M(b(t)`,recipe-list`)},[(p(!0),g(h,null,F(b(k),e=>(p(),g("article",{id:e.id.toLowerCase(),key:e.id,class:M(b(t)`,recipe`)},[f("h3",{class:M(b(t)`,recipe-title`)},y(e.id)+" â "+y(e.title),3),f("p",{class:M(b(t)`,recipe-text`)},y(e.expected),3),f("p",{class:M(b(t)`,recipe-usage`)},[o[19]||(o[19]=f("strong",null,"Файл авÑомаÑиÑеÑкого ÑеÑÑа:",-1)),o[20]||(o[20]=v()),f("a",{href:e.source.href,rel:"noopener noreferrer",target:"_blank"},[f("code",null,y(e.source.label),1)],8,yn)],2)],10,bn))),128))],2)],2)
1],64))}};export{vn as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.