@mohsinonxrm/pptb-commandbar-studio 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +363 -99
  2. package/LICENSE +661 -661
  3. package/README.md +343 -316
  4. package/SECURITY.md +62 -0
  5. package/dist/assets/BulkPublishModal-DqX2QmUD.js +29 -0
  6. package/dist/assets/CommandEditorPanel-DidGBtFC.js +1 -0
  7. package/dist/assets/CommandPalette-AuDfsF8l.js +1 -0
  8. package/dist/assets/ConflictDrawer-DxQ_jd-x.js +1 -0
  9. package/dist/assets/CrmParameterEditor-BdmP65mF.js +1 -0
  10. package/dist/assets/DiffViewer-BZuqvP4f.js +7 -0
  11. package/dist/assets/HideInsteadOfDeleteModal-BYHCTZrG.js +1 -0
  12. package/dist/assets/IconPickerModal-Bw0C7KwV.js +1 -0
  13. package/dist/assets/ImportXmlModal-B8NgiUDZ.js +1 -0
  14. package/dist/assets/LocalizationEditor-tmniX5PC.js +1 -0
  15. package/dist/assets/MonacoEditor-Bbg9u2FW.js +2 -0
  16. package/dist/assets/NewButtonModal-BVvlbCv4.js +1 -0
  17. package/dist/assets/NewGroupModal-CgQy-uo4.js +1 -0
  18. package/dist/assets/NewTabModal-B_2-kwAx.js +1 -0
  19. package/dist/assets/RuleEditorPanel-BkNwBgaP.js +1 -0
  20. package/dist/assets/ScalingEditorPanel-ezMkzvG1.js +1 -0
  21. package/dist/assets/TabDisplayRulesPanel-trzExQ1T.js +1 -0
  22. package/dist/assets/UrlComposerModal-BlVXHKRM.js +1 -0
  23. package/dist/assets/WebResourceBrowser-DaPOZQ5X.js +1 -0
  24. package/dist/assets/XmlDrawer-BI6Wy6kL.js +2 -0
  25. package/dist/assets/crmParameters-rgfZhhzN.js +1 -0
  26. package/dist/assets/cssMode-DdC7kBk-.js +1 -0
  27. package/dist/assets/{dnd-DHB99ZH7.js → dnd-fsSwRnQv.js} +2 -2
  28. package/dist/assets/{editor.worker-CdQrwHl8.js → editor.worker-1APKdqmi.js} +2 -2
  29. package/dist/assets/fluent-icons-DxKNRZ1A.js +1 -0
  30. package/dist/assets/fluent-ui-D7EtYwEg.js +43 -0
  31. package/dist/assets/{freemarker2-B8bME0pA.js → freemarker2-DDn-Wpd6.js} +1 -1
  32. package/dist/assets/{handlebars-zIyCxTW6.js → handlebars-Ck_SjSJx.js} +1 -1
  33. package/dist/assets/{html-B5hFqu3X.js → html-BaJUqhKx.js} +1 -1
  34. package/dist/assets/htmlMode-CnYhJfhG.js +1 -0
  35. package/dist/assets/index-Bu7BlRFk.js +139 -0
  36. package/dist/assets/{javascript-BQGsYMat.js → javascript-2UlV1Qbm.js} +1 -1
  37. package/dist/assets/{jsonMode-CR0b-9Un.js → jsonMode-BmSpB9yr.js} +1 -1
  38. package/dist/assets/{liquid-DLq8jbP8.js → liquid-CE2reFvH.js} +1 -1
  39. package/dist/assets/{lspLanguageFeatures-C3buAG32.js → lspLanguageFeatures-BvbzEddk.js} +2 -2
  40. package/dist/assets/{mdx-5ni22WXY.js → mdx-BvcZv3tC.js} +1 -1
  41. package/dist/assets/{monaco-BLZnQb2P.js → monaco-Bx8A1Vm1.js} +4 -4
  42. package/dist/assets/monaco-Dprb6f6S.css +1 -0
  43. package/dist/assets/{python-F20Pd69B.js → python-MTPSN2vk.js} +1 -1
  44. package/dist/assets/{razor-3xmsG6cc.js → razor-Ccq_CgR8.js} +1 -1
  45. package/dist/assets/ruleKinds-B9hACGaq.js +1 -0
  46. package/dist/assets/{server.browser-DfdiBs1P.js → server.browser-C3R9jebn.js} +1 -1
  47. package/dist/assets/{tsMode-Cyusk9p4.js → tsMode-2cv3qhqp.js} +1 -1
  48. package/dist/assets/{typescript-BXT-ECX3.js → typescript-BD6t7JEG.js} +1 -1
  49. package/dist/assets/webResourceService-CvyHBu7T.js +1 -0
  50. package/dist/assets/{xml-Cwzeco8o.js → xml-DJGPA7j9.js} +1 -1
  51. package/dist/assets/xmlValidator-D7JG-eNC.js +3 -0
  52. package/dist/assets/{yaml-BHUePD-R.js → yaml-Cpl0dvFM.js} +1 -1
  53. package/dist/icons/icon.svg +16 -0
  54. package/dist/index.html +24 -18
  55. package/index.html +18 -12
  56. package/package.json +18 -32
  57. package/dist/assets/BulkPublishModal-DlglMah4.js +0 -29
  58. package/dist/assets/CommandEditorPanel-4pYnil3i.js +0 -1
  59. package/dist/assets/CommandPalette-iYxzI2G_.js +0 -1
  60. package/dist/assets/ConflictDrawer-DBPRRkoa.js +0 -1
  61. package/dist/assets/DiffViewer-DFBJPZKA.js +0 -7
  62. package/dist/assets/IconPickerModal-Bg0Zc8UZ.js +0 -1
  63. package/dist/assets/ImportXmlModal-BccMoaDv.js +0 -3
  64. package/dist/assets/LocalizationEditor-DVZy2uLy.js +0 -1
  65. package/dist/assets/MonacoEditor-DFYisBG6.js +0 -2
  66. package/dist/assets/NewButtonModal-D5Hz1yx4.js +0 -1
  67. package/dist/assets/NewGroupModal-BgTVG-VJ.js +0 -1
  68. package/dist/assets/NewTabModal-7-ZPcPi-.js +0 -1
  69. package/dist/assets/RuleEditorPanel-BwQzOQBe.js +0 -1
  70. package/dist/assets/ScalingEditorPanel-B221zNLL.js +0 -1
  71. package/dist/assets/TabDisplayRulesPanel-drKzEO_E.js +0 -1
  72. package/dist/assets/UrlComposerModal-Bnifp4oB.js +0 -1
  73. package/dist/assets/WebResourceBrowser-qtcNTNge.js +0 -1
  74. package/dist/assets/XmlDrawer-CN941TbU.js +0 -2
  75. package/dist/assets/cssMode-DFSY9yCW.js +0 -1
  76. package/dist/assets/fluent-icons-DiKr_qRE.js +0 -1
  77. package/dist/assets/fluent-ui-kUA2U4Gr.js +0 -43
  78. package/dist/assets/htmlMode-BmPxEBms.js +0 -1
  79. package/dist/assets/index-DjHxPFpB.js +0 -6
  80. package/dist/assets/monaco-Dvl_Svmm.css +0 -1
  81. package/dist/assets/webResourceService-Ck07E3GN.js +0 -1
  82. package/dist/assets/xmlGenerator-DEaVrfZJ.js +0 -130
  83. package/dist/stats.html +0 -4949
  84. package/npm-shrinkwrap.json +0 -13253
@@ -1 +1 @@
1
- import{l as e}from"./monaco-BLZnQb2P.js";const n={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],onEnterRules:[{beforeText:/^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,afterText:/^\s*\*\/$/,action:{indentAction:e.IndentAction.IndentOutdent,appendText:" * "}},{beforeText:/^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,action:{indentAction:e.IndentAction.None,appendText:" * "}},{beforeText:/^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,action:{indentAction:e.IndentAction.None,appendText:"* "}},{beforeText:/^(\t|(\ \ ))*\ \*\/\s*$/,action:{indentAction:e.IndentAction.None,removeText:1}}],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string","comment"]},{open:"`",close:"`",notIn:["string","comment"]},{open:"/**",close:" */",notIn:["string"]}],folding:{markers:{start:new RegExp("^\\s*//\\s*#?region\\b"),end:new RegExp("^\\s*//\\s*#?endregion\\b")}}},o={defaultToken:"invalid",tokenPostfix:".ts",keywords:["abstract","any","as","asserts","bigint","boolean","break","case","catch","class","continue","const","constructor","debugger","declare","default","delete","do","else","enum","export","extends","false","finally","for","from","function","get","if","implements","import","in","infer","instanceof","interface","is","keyof","let","module","namespace","never","new","null","number","object","out","package","private","protected","public","override","readonly","require","global","return","satisfies","set","static","string","super","switch","symbol","this","throw","true","try","type","typeof","undefined","unique","unknown","var","void","while","with","yield","async","await","of"],operators:["<=",">=","==","!=","===","!==","=>","+","-","**","*","/","%","++","--","<<","</",">>",">>>","&","|","^","!","~","&&","||","??","?",":","=","+=","-=","*=","**=","/=","%=","<<=",">>=",">>>=","&=","|=","^=","@"],symbols:/[=><!~?:&|+\-*\/\^%]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,digits:/\d+(_+\d+)*/,octaldigits:/[0-7]+(_+[0-7]+)*/,binarydigits:/[0-1]+(_+[0-1]+)*/,hexdigits:/[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/,regexpctl:/[(){}\[\]\$\^|\-*+?\.]/,regexpesc:/\\(?:[bBdDfnrstvwWn0\\\/]|@regexpctl|c[A-Z]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})/,tokenizer:{root:[[/[{}]/,"delimiter.bracket"],{include:"common"}],common:[[/#?[a-z_$][\w$]*/,{cases:{"@keywords":"keyword","@default":"identifier"}}],[/[A-Z][\w\$]*/,"type.identifier"],{include:"@whitespace"},[/\/(?=([^\\\/]|\\.)+\/([dgimsuy]*)(\s*)(\.|;|,|\)|\]|\}|$))/,{token:"regexp",bracket:"@open",next:"@regexp"}],[/[()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/!(?=([^=]|$))/,"delimiter"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/(@digits)[eE]([\-+]?(@digits))?/,"number.float"],[/(@digits)\.(@digits)([eE][\-+]?(@digits))?/,"number.float"],[/0[xX](@hexdigits)n?/,"number.hex"],[/0[oO]?(@octaldigits)n?/,"number.octal"],[/0[bB](@binarydigits)n?/,"number.binary"],[/(@digits)n?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string_double"],[/'/,"string","@string_single"],[/`/,"string","@string_backtick"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@jsdoc"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],jsdoc:[[/[^\/*]+/,"comment.doc"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],regexp:[[/(\{)(\d+(?:,\d*)?)(\})/,["regexp.escape.control","regexp.escape.control","regexp.escape.control"]],[/(\[)(\^?)(?=(?:[^\]\\\/]|\\.)+)/,["regexp.escape.control",{token:"regexp.escape.control",next:"@regexrange"}]],[/(\()(\?:|\?=|\?!)/,["regexp.escape.control","regexp.escape.control"]],[/[()]/,"regexp.escape.control"],[/@regexpctl/,"regexp.escape.control"],[/[^\\\/]/,"regexp"],[/@regexpesc/,"regexp.escape"],[/\\\./,"regexp.invalid"],[/(\/)([dgimsuy]*)/,[{token:"regexp",bracket:"@close",next:"@pop"},"keyword.other"]]],regexrange:[[/-/,"regexp.escape.control"],[/\^/,"regexp.invalid"],[/@regexpesc/,"regexp.escape"],[/[^\]]/,"regexp"],[/\]/,{token:"regexp.escape.control",next:"@pop",bracket:"@close"}]],string_double:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],string_single:[[/[^\\']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/'/,"string","@pop"]],string_backtick:[[/\$\{/,{token:"delimiter.bracket",next:"@bracketCounting"}],[/[^\\`$]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/`/,"string","@pop"]],bracketCounting:[[/\{/,"delimiter.bracket","@bracketCounting"],[/\}/,"delimiter.bracket","@pop"],{include:"common"}]}};export{n as conf,o as language};
1
+ import{d as e}from"./monaco-Bx8A1Vm1.js";const n={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],onEnterRules:[{beforeText:/^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,afterText:/^\s*\*\/$/,action:{indentAction:e.IndentAction.IndentOutdent,appendText:" * "}},{beforeText:/^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,action:{indentAction:e.IndentAction.None,appendText:" * "}},{beforeText:/^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,action:{indentAction:e.IndentAction.None,appendText:"* "}},{beforeText:/^(\t|(\ \ ))*\ \*\/\s*$/,action:{indentAction:e.IndentAction.None,removeText:1}}],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string","comment"]},{open:"`",close:"`",notIn:["string","comment"]},{open:"/**",close:" */",notIn:["string"]}],folding:{markers:{start:new RegExp("^\\s*//\\s*#?region\\b"),end:new RegExp("^\\s*//\\s*#?endregion\\b")}}},o={defaultToken:"invalid",tokenPostfix:".ts",keywords:["abstract","any","as","asserts","bigint","boolean","break","case","catch","class","continue","const","constructor","debugger","declare","default","delete","do","else","enum","export","extends","false","finally","for","from","function","get","if","implements","import","in","infer","instanceof","interface","is","keyof","let","module","namespace","never","new","null","number","object","out","package","private","protected","public","override","readonly","require","global","return","satisfies","set","static","string","super","switch","symbol","this","throw","true","try","type","typeof","undefined","unique","unknown","var","void","while","with","yield","async","await","of"],operators:["<=",">=","==","!=","===","!==","=>","+","-","**","*","/","%","++","--","<<","</",">>",">>>","&","|","^","!","~","&&","||","??","?",":","=","+=","-=","*=","**=","/=","%=","<<=",">>=",">>>=","&=","|=","^=","@"],symbols:/[=><!~?:&|+\-*\/\^%]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,digits:/\d+(_+\d+)*/,octaldigits:/[0-7]+(_+[0-7]+)*/,binarydigits:/[0-1]+(_+[0-1]+)*/,hexdigits:/[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/,regexpctl:/[(){}\[\]\$\^|\-*+?\.]/,regexpesc:/\\(?:[bBdDfnrstvwWn0\\\/]|@regexpctl|c[A-Z]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})/,tokenizer:{root:[[/[{}]/,"delimiter.bracket"],{include:"common"}],common:[[/#?[a-z_$][\w$]*/,{cases:{"@keywords":"keyword","@default":"identifier"}}],[/[A-Z][\w\$]*/,"type.identifier"],{include:"@whitespace"},[/\/(?=([^\\\/]|\\.)+\/([dgimsuy]*)(\s*)(\.|;|,|\)|\]|\}|$))/,{token:"regexp",bracket:"@open",next:"@regexp"}],[/[()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/!(?=([^=]|$))/,"delimiter"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/(@digits)[eE]([\-+]?(@digits))?/,"number.float"],[/(@digits)\.(@digits)([eE][\-+]?(@digits))?/,"number.float"],[/0[xX](@hexdigits)n?/,"number.hex"],[/0[oO]?(@octaldigits)n?/,"number.octal"],[/0[bB](@binarydigits)n?/,"number.binary"],[/(@digits)n?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string_double"],[/'/,"string","@string_single"],[/`/,"string","@string_backtick"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@jsdoc"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],jsdoc:[[/[^\/*]+/,"comment.doc"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],regexp:[[/(\{)(\d+(?:,\d*)?)(\})/,["regexp.escape.control","regexp.escape.control","regexp.escape.control"]],[/(\[)(\^?)(?=(?:[^\]\\\/]|\\.)+)/,["regexp.escape.control",{token:"regexp.escape.control",next:"@regexrange"}]],[/(\()(\?:|\?=|\?!)/,["regexp.escape.control","regexp.escape.control"]],[/[()]/,"regexp.escape.control"],[/@regexpctl/,"regexp.escape.control"],[/[^\\\/]/,"regexp"],[/@regexpesc/,"regexp.escape"],[/\\\./,"regexp.invalid"],[/(\/)([dgimsuy]*)/,[{token:"regexp",bracket:"@close",next:"@pop"},"keyword.other"]]],regexrange:[[/-/,"regexp.escape.control"],[/\^/,"regexp.invalid"],[/@regexpesc/,"regexp.escape"],[/[^\]]/,"regexp"],[/\]/,{token:"regexp.escape.control",next:"@pop",bracket:"@close"}]],string_double:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],string_single:[[/[^\\']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/'/,"string","@pop"]],string_backtick:[[/\$\{/,{token:"delimiter.bracket",next:"@bracketCounting"}],[/[^\\`$]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/`/,"string","@pop"]],bracketCounting:[[/\{/,"delimiter.bracket","@bracketCounting"],[/\}/,"delimiter.bracket","@pop"],{include:"common"}]}};export{n as conf,o as language};
@@ -0,0 +1 @@
1
+ import{b as S,c as w}from"./index-Bu7BlRFk.js";function f(){const e=window.dataverseAPI;if(!e)throw new Error("dataverseAPI is not available in the current runtime");return e}const $={1:"html",2:"css",3:"js",4:"xml",5:"png",6:"jpg",7:"gif",8:"xap",9:"xsl",10:"ico",11:"svg",12:"resx"};function h(e){return $[e]??"xml"}async function W(e,n){let s="webresourceset?$select=webresourceid,name,displayname,description,webresourcetype,modifiedon,ismanaged&$orderby=name asc";if(n!==void 0){const t=Object.entries($).find(([,o])=>o===n)?.[0];t&&(s+=`&$filter=webresourcetype eq ${t}`)}return(await e.queryData(s)).value.map(t=>{const o=t;return{id:String(o.webresourceid??""),name:String(o.name??""),displayName:o.displayname?String(o.displayname):void 0,description:o.description?String(o.description):void 0,webResourceType:h(Number(o.webresourcetype??3)),modifiedOn:o.modifiedon?String(o.modifiedon):void 0,isCustom:o.ismanaged===!1}})}async function C(e,n){const s=await e.retrieve("webresource",n,["content"]);return s.content?String(s.content):""}const q=61;async function N(e,n,s){await e.execute({operationName:"AddSolutionComponent",operationType:"action",parameters:{ComponentId:n,ComponentType:q,SolutionUniqueName:s,AddRequiredComponents:!1}})}async function x(e,n,s,a,t={}){const{displayName:o,solutionUniqueName:r,keepExisting:d=!1}=t,u=await e.queryData(`webresourceset?$select=webresourceid&$filter=name eq '${n.replace(/'/g,"''")}'&$top=1`),m={name:n,content:s,webresourcetype:a,...o?{displayname:o}:{}};let c;if(u.value.length>0){const i=u.value[0],l=String(i.webresourceid??"");d||await e.update("webresource",l,m),c={id:l,created:!1,updated:!d}}else{const i=await e.create("webresource",m);c={id:String(i.id??""),created:!0,updated:!1}}if(r&&c.id){try{await N(e,c.id,r)}catch(i){throw new Error(`Web resource ${n} was saved but could not be added to solution ${r}: ${i instanceof Error?i.message:String(i)}`)}c.solutionUniqueName=r}return c}const b=40,y=(e,n)=>Array.from({length:Math.ceil(e.length/n)},(s,a)=>e.slice(a*n,(a+1)*n)),R=e=>`'${e.replace(/'/g,"''").replace(/[^A-Za-z0-9/._\-'~]/gu,n=>encodeURIComponent(n))}'`,v=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;async function E(e,n,s){const a=n.map(u=>u.split(/[?#]/)[0].trim()).filter(Boolean),t=a.filter((u,m)=>a.findIndex(c=>c.toLowerCase()===u.toLowerCase())===m),o={};for(const u of t)o[u.toLowerCase()]={exists:!1,inSolution:!1};if(t.length===0)return o;const r=new Map;for(const u of y(t,b)){const m=u.map(i=>`name eq ${R(i)}`).join(" or "),c=await e.queryData(`webresourceset?$select=webresourceid,name,ismanaged&$filter=${m}`);for(const i of c.value??[]){const l=i,p=String(l.name??"").toLowerCase();if(!(p in o))continue;o[p]={exists:!0,inSolution:!1,managed:l.ismanaged===!0};const g=String(l.webresourceid??"").toLowerCase();v.test(g)&&r.set(g,p)}}const d=s?.replace(/[{}]/g,"");if(d&&v.test(d)&&r.size>0)for(const u of y([...r.keys()],b)){const m=u.map(i=>`objectid eq ${i}`).join(" or "),c=await e.queryData(`solutioncomponents?$select=objectid&$filter=_solutionid_value eq ${d} and componenttype eq ${q} and (${m})`);for(const i of c.value??[]){const l=r.get(String(i.objectid??"").toLowerCase());l&&(o[l].inSolution=!0)}}return o}async function _(e,n){return E(f(),e,n)}async function A(e){return W(f(),e)}async function D(e){return C(f(),e)}async function T(e){const n=f(),s=e.replace(/'/g,"''"),a=await n.queryData(`webresourceset?$select=webresourceid,name,displayname,webresourcetype,ismanaged&$filter=name eq '${s}'&$top=1`);if(!a.value?.length)return null;const t=a.value[0];return{id:String(t.webresourceid??""),name:String(t.name??""),displayName:t.displayname?String(t.displayname):void 0,webResourceType:h(Number(t.webresourcetype??3)),isCustom:t.ismanaged===!1}}async function I(e,n,s,a={}){const t=S.getState().activeSolution,o=a.solutionUniqueName??(t&&!t.isManaged?t.uniqueName:void 0),r=await x(f(),e,n,s,{...a,solutionUniqueName:o});if(!o){const d=t?`the active solution ${t.uniqueName} is managed`:"no solution is selected";r.solutionWarning=`Web resource ${e} was saved but not added to any solution because ${d}. It is only in the Default solution — select an unmanaged solution and save it again so it travels with your customizations.`,w.getState().logWarn("webresource",r.solutionWarning)}return r}async function P(e,n){const s=n??await T(e);if(!s?.id)throw new Error(`No web resource named ${e} exists in this environment.`);const a=s.id;if(s.isCustom===!1){const o=`Web resource ${e} is managed, so it isn't added to your solution. The solution that provides it must be installed wherever you import your customizations.`;return w.getState().logWarn("webresource",o),{solutionWarning:o}}const t=S.getState().activeSolution;if(!t||t.isManaged){const o=t?`the active solution ${t.uniqueName} is managed`:"no solution is selected",r=`Web resource ${e} was not added to any solution because ${o}. Select an unmanaged solution and pick the icon again so it travels with your customizations.`;return w.getState().logWarn("webresource",r),{solutionWarning:r}}return await N(f(),a,t.uniqueName),{solutionUniqueName:t.uniqueName}}async function j(e){const n=f(),s=`<importexportxml><webresources><webresource>${e}</webresource></webresources></importexportxml>`;await n.execute({operationName:"PublishXml",operationType:"action",parameters:{ParameterXml:s}})}export{T as a,D as b,_ as c,P as d,A as l,j as p,I as s};
@@ -1 +1 @@
1
- import{l as e}from"./monaco-BLZnQb2P.js";const n={comments:{blockComment:["<!--","-->"]},brackets:[["<",">"]],autoClosingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],surroundingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],onEnterRules:[{beforeText:new RegExp("<([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$","i"),afterText:/^<\/([_:\w][_:\w-.\d]*)\s*>$/i,action:{indentAction:e.IndentAction.IndentOutdent}},{beforeText:new RegExp("<(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$","i"),action:{indentAction:e.IndentAction.Indent}}]},o={defaultToken:"",tokenPostfix:".xml",ignoreCase:!0,qualifiedName:/(?:[\w\.\-]+:)?[\w\.\-]+/,tokenizer:{root:[[/[^<&]+/,""],{include:"@whitespace"},[/(<)(@qualifiedName)/,[{token:"delimiter"},{token:"tag",next:"@tag"}]],[/(<\/)(@qualifiedName)(\s*)(>)/,[{token:"delimiter"},{token:"tag"},"",{token:"delimiter"}]],[/(<\?)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/(<\!)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/<\!\[CDATA\[/,{token:"delimiter.cdata",next:"@cdata"}],[/&\w+;/,"string.escape"]],cdata:[[/[^\]]+/,""],[/\]\]>/,{token:"delimiter.cdata",next:"@pop"}],[/\]/,""]],tag:[[/[ \t\r\n]+/,""],[/(@qualifiedName)(\s*=\s*)("[^"]*"|'[^']*')/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">?\/]*|'[^'>?\/]*)(?=[\?\/]\>)/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">]*|'[^'>]*)/,["attribute.name","","attribute.value"]],[/@qualifiedName/,"attribute.name"],[/\?>/,{token:"delimiter",next:"@pop"}],[/(\/)(>)/,[{token:"tag"},{token:"delimiter",next:"@pop"}]],[/>/,{token:"delimiter",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[/<!--/,{token:"comment",next:"@comment"}]],comment:[[/[^<\-]+/,"comment.content"],[/-->/,{token:"comment",next:"@pop"}],[/<!--/,"comment.content.invalid"],[/[<\-]/,"comment.content"]]}};export{n as conf,o as language};
1
+ import{d as e}from"./monaco-Bx8A1Vm1.js";const n={comments:{blockComment:["<!--","-->"]},brackets:[["<",">"]],autoClosingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],surroundingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],onEnterRules:[{beforeText:new RegExp("<([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$","i"),afterText:/^<\/([_:\w][_:\w-.\d]*)\s*>$/i,action:{indentAction:e.IndentAction.IndentOutdent}},{beforeText:new RegExp("<(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$","i"),action:{indentAction:e.IndentAction.Indent}}]},o={defaultToken:"",tokenPostfix:".xml",ignoreCase:!0,qualifiedName:/(?:[\w\.\-]+:)?[\w\.\-]+/,tokenizer:{root:[[/[^<&]+/,""],{include:"@whitespace"},[/(<)(@qualifiedName)/,[{token:"delimiter"},{token:"tag",next:"@tag"}]],[/(<\/)(@qualifiedName)(\s*)(>)/,[{token:"delimiter"},{token:"tag"},"",{token:"delimiter"}]],[/(<\?)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/(<\!)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/<\!\[CDATA\[/,{token:"delimiter.cdata",next:"@cdata"}],[/&\w+;/,"string.escape"]],cdata:[[/[^\]]+/,""],[/\]\]>/,{token:"delimiter.cdata",next:"@pop"}],[/\]/,""]],tag:[[/[ \t\r\n]+/,""],[/(@qualifiedName)(\s*=\s*)("[^"]*"|'[^']*')/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">?\/]*|'[^'>?\/]*)(?=[\?\/]\>)/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">]*|'[^'>]*)/,["attribute.name","","attribute.value"]],[/@qualifiedName/,"attribute.name"],[/\?>/,{token:"delimiter",next:"@pop"}],[/(\/)(>)/,[{token:"tag"},{token:"delimiter",next:"@pop"}]],[/>/,{token:"delimiter",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[/<!--/,{token:"comment",next:"@comment"}]],comment:[[/[^<\-]+/,"comment.content"],[/-->/,{token:"comment",next:"@pop"}],[/<!--/,"comment.content.invalid"],[/[<\-]/,"comment.content"]]}};export{n as conf,o as language};
@@ -0,0 +1,3 @@
1
+ import{T as E,U as Q,V as B,W as Z,p as ee}from"./index-Bu7BlRFk.js";import{D as te,E as ne}from"./ruleKinds-B9hACGaq.js";import{C as oe,i as se}from"./crmParameters-rgfZhhzN.js";const ae=["Mscrm.HideOnModern","Mscrm.ShowOnlyOnModern"];function L(l,c){const b=l.indexOf(c);return b<0?void 0:`Line ${l.slice(0,b).split(/\r?\n/).length}`}function ye(l,c,b){const d=[],y=new DOMParser().parseFromString(l,"application/xml"),$=y.querySelector("parsererror");if($){const i=$.textContent?.trim()??"Unknown",u=i.match(/line\s+(\d+)/i);return d.push({message:`XML parse error: ${i}`,lineHint:u?`Line ${u[1]}`:void 0}),d}const f=new Set([]);return y.querySelectorAll("[Id]").forEach(i=>{const u=i.getAttribute("Id")??"";if(/\s/.test(u)){const A=L(l,`Id="${u}"`);d.push({message:`Element ID "${u}" contains invalid whitespace characters`,elementId:u,lineHint:A})}}),y.querySelectorAll("[LabelText]").forEach(i=>{const u=i.getAttribute("LabelText")??"",A=u.match(/^\$LocLabels:(.+)$/);if(A&&f.size>0&&!f.has(A[1])){const g=i.getAttribute("Id")??"",I=L(l,g?`Id="${g}"`:`LabelText="${u}"`);d.push({message:`Button label reference "$LocLabels:${A[1]}" has no matching LocLabel entry`,elementId:g||void 0,lineHint:I})}}),(l.includes("& ")||l.includes(`&
2
+ `))&&d.push({message:'URL may contain an unescaped "&" — all ampersands in XML must be written as &amp;',lineHint:L(l,"& ")??L(l,`&
3
+ `)}),y.querySelectorAll("Group").forEach(i=>{const u=[];i.querySelectorAll(":scope > Controls > Button, :scope > Controls > FlyoutAnchor, :scope > Controls > SplitButton").forEach(A=>{const g=parseInt(A.getAttribute("Sequence")??"0",10);if(u.includes(g)){const I=i.getAttribute("Id")??"?";d.push({message:`Two elements share Sequence "${g}" in group "${I}"`,elementId:I,lineHint:L(l,`Sequence="${g}"`)})}u.push(g)})}),d.push(...ie(y,l)),d}const j=new Set(["BoolParameter","CrmParameter","DecimalParameter","IntParameter","StringParameter"]);function p(l){return Array.from(l.children)}function W(l,c){return c==="enable"?te.has(l):ne.has(l)}function ie(l,c){const b=[],d=(f,i,u)=>b.push({message:f,elementId:u,lineHint:L(c,i)}),w=(f,i,u)=>b.push({message:f,elementId:u,lineHint:L(c,i),severity:"warning"}),y=l.querySelector("RibbonDiffXml > RuleDefinitions"),$=[{tag:"EnableRule",label:"Enable",container:"enable"},{tag:"DisplayRule",label:"Display",container:"display"}];for(const{tag:f,label:i,container:u}of $)y?.querySelectorAll(`:scope > ${f}s > ${f}`).forEach(A=>{const g=A.getAttribute("Id")??"",I=p(A);I.length===0&&d(`${i} rule "${g}" has no steps — the schema requires at least one`,`Id="${g}"`,g);const v=S=>{W(S.tagName,u)&&w(`${i} rule "${g}" contains ${S.tagName}, which RibbonTypes.xsd only allows in ${u==="enable"?"display":"enable"} rules`,`<${S.tagName}`,g)};for(const S of I){if(S.tagName!=="OrRule"){v(S);continue}const R=p(S);R.filter(N=>N.tagName==="Or").length<2&&d(`OrRule in ${i.toLowerCase()} rule "${g}" needs at least 2 <Or> children (found ${R.filter(N=>N.tagName==="Or").length})`,"<OrRule",g);for(const N of R){const C=p(N);C.length===0&&d(`Empty <Or> in rule "${g}"`,"<Or",g);for(const O of C)O.tagName==="OrRule"?d(`Rule "${g}": an <Or> cannot contain another OrRule`,"<OrRule",g):v(O)}}});return y||l.querySelectorAll("OrRule").forEach(f=>{const i=f.querySelectorAll(":scope > Or").length;i<2&&d(`OrRule requires at least 2 <Or> children (found ${i})`,"<OrRule")}),l.querySelectorAll("JavaScriptFunction, CustomRule").forEach(f=>{for(const i of p(f)){if(!j.has(i.tagName))continue;i.hasAttribute("Name")&&d(`${i.tagName} inside <${f.tagName}> must not have a Name attribute (only <Url> parameters are named)`,`<${i.tagName} Name=`);const u=i.getAttribute("Value")??"";i.tagName==="CrmParameter"&&!oe.has(u)&&d(`CrmParameter Value "${u}" is not a valid CrmParameterValue`,`Value="${u}"`)}}),l.querySelectorAll("Url").forEach(f=>{for(const i of p(f)){if(!j.has(i.tagName))continue;i.getAttribute("Name")||d(`${i.tagName} inside <Url> requires a Name (the query-string key)`,`<${i.tagName}`);const u=i.getAttribute("Value")??"";i.tagName==="CrmParameter"&&!se(u)&&d(`CrmParameter Value "${u}" is not allowed in a <Url> action (CrmNamedParameterValue)`,`Value="${u}"`)}}),l.querySelector("RibbonDiffXml > Scalings")&&d('<Scalings> is not allowed in RibbonDiffXml — scaling changes are CustomActions with Location="{tabId}.Scaling._children"',"<Scalings"),l.querySelectorAll("CustomAction > CommandUIDefinition > Tab").forEach(f=>{const i=f.getAttribute("Id")??"",u=p(f).map(I=>I.tagName),A=u.indexOf("Scaling"),g=u.indexOf("Groups");(A<0||g>=0&&A>g)&&d(`Tab "${i}" needs a <Scaling Id> element before <Groups>`,`Id="${i}"`,i)}),l.querySelectorAll("TabDisplayRule > DisplayRules").forEach(()=>{d("TabDisplayRule rules must be direct children — remove the <DisplayRules> wrapper","<TabDisplayRule")}),b}const re=["LabelText","ToolTipTitle","ToolTipDescription","Alt","Title","Description"],ce=new Set(["powerFx","customApi"]),le={powerFx:"Power Fx",customApi:"Custom API"};function ue(l){return[...new Set(l.actions.map(c=>c.kind).filter(c=>ce.has(c)))]}const de=/^\$LocLabels:(.+)$/,K=/^\$webresource:([^?#]+)/i,fe=new Set(["ModernImage","Image16by16","Image32by32"]),x=new Set(["Tab","Group"]),X=new Set(["main_system_library.js"]),me=new Set(["FlyoutAnchor","SplitButton"]),he=new Set(["Button","FlyoutAnchor","SplitButton","TextBox","ComboBox","CheckBox"]),H=/^(.+)\.Scaling\._children$/,F=l=>/^(Mscrm|Microsoft)\./.test(l);function Y(l){const c=[],b=[],d=new DOMParser;for(const w of Object.keys(l))for(const[y,$]of l[w]){const f=d.parseFromString($,"application/xml");if(f.querySelector("parsererror")){b.push({severity:"error",code:"xml-parse",message:`${w} element ${y} is not well-formed XML`,elementId:y});continue}c.push({part:w,key:`${w}:${y}`,el:f.documentElement})}return{elements:c,errors:b}}function T(l){return[l,...Array.from(l.getElementsByTagName("*"))]}function J(l){return typeof l=="string"?ee(l):l}function Ae(l){let c;try{c=J(l)}catch{return[]}const b=new Map;for(const{el:d}of Y(c).elements)for(const w of T(d))for(const y of Array.from(w.attributes)){const $=K.exec(y.value.trim())?.[1],f=$?.toLowerCase();$&&f&&!X.has(f)&&!b.has(f)&&b.set(f,$)}return[...b.values()]}const V=l=>{const c=l.trim();return c&&!c.includes(".")?`Mscrm.Templates.${c}`:c};function we(l,c={}){let b;try{b=J(l)}catch(e){return[{severity:"error",code:"xml-parse",message:e instanceof Error?e.message:String(e)}]}const{elements:d,errors:w}=Y(b),y=c.changedKeys?new Set(c.changedKeys):null,$=e=>!y||y.has(e),f=new Set(c.newKeys??[]),i=(e,o,n,a,t=!1)=>{const s=(Array.isArray(o)?o:[o]).some($);w.push({severity:t||!s?"warning":"error",code:e,message:s?n:`${n} (already in the published customizations)`,elementId:a})},u=d.filter(e=>e.part==="customActions"),A=d.filter(e=>e.part==="commandDefinitions"),g=new Map((c.commands??[]).map(e=>[e.id,e]));for(const{key:e,el:o}of A){const n=o.getAttribute("Id")??"",a=g.get(n);if(!a||!$(e))continue;const t=ue(a);t.length!==0&&i("dropped-action",e,`Command ${n} has a ${t.map(s=>le[s]??s).join(" / ")} action — classic ribbon commands can't run it, so it would be dropped; remove the action`,n)}const I=new Set;for(const{el:e}of u)if(e.tagName==="CustomAction")for(const o of Array.from(e.getElementsByTagName("*")))o.getAttribute("Command")===E&&I.add(o.getAttribute("Id")??"");for(const{key:e,el:o}of u){if(o.tagName!=="HideCustomAction")continue;const n=o.getAttribute("Location")??"";!I.has(n)&&!Q({id:n,commandId:E})||i("open-record-hidden",e,`${n} is hidden, but it carries the record open override (${E}) — Unified Interface may then open records as usual or fail to open them; unhide it, or turn the override off`,n,!0)}for(const{key:e,el:o}of A){if(o.getAttribute("Id")!==E)continue;const n=p(o).filter(t=>t.tagName==="DisplayRules").flatMap(t=>p(t).map(s=>s.getAttribute("Id")??s.tagName));if(n.length===0)continue;const a=ae.filter(t=>n.includes(t));i("open-record-hidden",e,`${E} has display rules (${n.join(", ")})${a.length>0?` — ${a.join(" + ")} hide its button`:""}: where they hide the "Open record" button, the record open override may stop working; the button must stay shown`,E,!0)}for(const{key:e,el:o}of u)for(const n of Array.from(o.getElementsByTagName("*"))){if(!me.has(n.tagName)||p(n).some(t=>t.tagName==="Menu"))continue;const a=n.getAttribute("Id")??"";i("menu-missing",e,`${n.tagName} ${a} has no <Menu> — it would publish as an empty drop-down`,a)}const v=new Set(c.menuControlsIds??[]);for(const{key:e,el:o}of u){const n=o.getAttribute("Location")??"",a=n.endsWith("._children")&&v.has(n.slice(0,-10));for(const t of Array.from(o.getElementsByTagName("*"))){const s=a||!!t.parentElement?.closest("Menu");for(const r of re){const h=t.getAttribute(r);if(!h?.startsWith("$LocLabels:"))continue;const m=h.slice(11);m.length<=B||i("label-id-length",e,`${t.tagName} ${t.getAttribute("Id")??""} uses label ${m} (${m.length} characters)`+(s?`: a menu item's label id may have at most ${B} characters, or the publish fails after the import — give the control a shorter id`:`: label ids over ${B} characters fail inside menus; consider a shorter control id`),t.getAttribute("Id")??void 0,!s)}}}if(c.known?.commandIds){const e=new Set([...b.commandDefinitions.keys(),...c.known.commandIds]);for(const{key:o,el:n}of u)for(const a of Array.from(n.getElementsByTagName("*"))){const t=a.getAttribute("Command");if(!t||e.has(t)||x.has(a.tagName))continue;const s=a.getAttribute("Id")??"";i("undefined-command",o,`${a.tagName} ${s} uses command ${t}, which is defined neither in the customizations nor in the loaded ribbon`,s,F(t))}}const S={EnableRule:c.known?.enableRuleIds?new Set([...b.enableRules.keys(),...c.known.enableRuleIds]):null,DisplayRule:c.known?.displayRuleIds?new Set([...b.displayRules.keys(),...c.known.displayRuleIds]):null};for(const{key:e,el:o}of A){const n=o.getAttribute("Id")??"",a=p(o).filter(t=>t.tagName==="EnableRules"||t.tagName==="DisplayRules").flatMap(p);for(const t of a){const s=S[t.tagName],r=t.getAttribute("Id");!s||!r||s.has(r)||i("undefined-rule",e,`Command ${n} uses ${t.tagName==="EnableRule"?"enable":"display"} rule ${r}, which is defined neither in the customizations nor in the loaded ribbon`,n,F(r))}}for(const{part:e,key:o,el:n}of d){if(e!=="enableRules"&&e!=="displayRules")continue;const a=e==="enableRules"?"enable":"display",t=n.getAttribute("Id")??"",s=p(n).flatMap(r=>r.tagName==="OrRule"?p(r).filter(h=>h.tagName==="Or").flatMap(p):[r]);for(const r of s)W(r.tagName,a)&&i("rule-placement",o,`${a==="enable"?"Enable":"Display"} rule ${t} contains ${r.tagName}, which the ribbon schema only allows in ${a==="enable"?"display":"enable"} rules`,t,!0)}for(const{key:e,el:o}of d)if(o.tagName!=="LocLabel")for(const n of T(o))for(const a of Array.from(n.attributes)){const t=de.exec(a.value)?.[1];if(!t||b.locLabels.has(t))continue;const s=n.getAttribute("Id")??void 0;s&&c.loadedAttributes?.[s]?.[a.name]===a.value||i("loclabel-missing",e,`${[n.tagName,s,a.name].filter(Boolean).join(" ")} references $LocLabels:${t}, which has no <LocLabel> in these customizations — the text won't resolve unless another solution defines the label`,s,!0)}if(c.webResources){const e=new Set;for(const{el:o}of d)for(const n of T(o))for(const a of Array.from(n.attributes)){const t=K.exec(a.value.trim())?.[1],s=t?.toLowerCase();if(!t||!s||X.has(s)||e.has(s))continue;const r=c.webResources[s];if(!r)continue;const h=n.getAttribute("Id")??void 0;r.exists?!r.inSolution&&!r.managed&&(e.add(s),w.push({severity:"warning",code:"webresource-not-in-solution",message:`Web resource ${t} isn't in the selected solution — the ribbon won't import into another environment without it`,elementId:h})):(e.add(s),w.push({severity:"warning",code:"webresource-missing",message:`Web resource ${t} (${n.tagName} ${a.name}) doesn't exist in this environment — ${fe.has(a.name)?"the button will show no icon":"the action or rule that loads it will fail when it runs"}`,elementId:h}))}}const R=new Map,N=e=>{let o=R.get(e);return o||R.set(e,o=new Map),o};for(const[e,o]of Object.entries(c.tabScaling??{})){for(const n of o.maxSizes)N(e).set(n.id,{...n,tag:"MaxSize"});for(const n of o.scales)N(e).set(n.id,{...n,tag:"Scale"})}const C=new Map(Object.entries(c.groupTemplates??{}).map(([e,o])=>[e,V(o)])),O=new Map(Object.entries(c.templateLayouts??{}));for(const{part:e,el:o}of d)if(e==="templates")for(const n of T(o).filter(a=>a.tagName==="GroupTemplate")){const a=p(n).filter(t=>t.tagName==="Layout").map(t=>t.getAttribute("Title")??"");O.set(n.getAttribute("Id")??"",a)}const U=[];for(const{key:e,el:o}of u){for(const s of Array.from(o.getElementsByTagName("Group"))){const r=s.getAttribute("Template");r&&C.set(s.getAttribute("Id")??"",V(r))}const n=[],a=H.exec(o.getAttribute("Location")??"")?.[1],t=p(o).find(s=>s.tagName==="CommandUIDefinition");if(a&&t)for(const s of p(t))n.push([a,s]);for(const s of Array.from(o.getElementsByTagName("Tab")))for(const r of p(s).filter(h=>h.tagName==="Scaling"))for(const h of p(r))n.push([s.getAttribute("Id")??"",h]);for(const[s,r]of n){if(r.tagName!=="MaxSize"&&r.tagName!=="Scale")continue;const h={id:r.getAttribute("Id")??"",tag:r.tagName,groupId:r.getAttribute("GroupId")??"",size:r.getAttribute("Size")??"",sequence:parseInt(r.getAttribute("Sequence")??"",10),key:e};N(s).set(h.id,h),U.push(h)}}for(const[e,o]of R){const n=new Map;for(const a of o.values())Number.isNaN(a.sequence)||n.set(a.sequence,[...n.get(a.sequence)??[],a]);for(const[a,t]of n){const s=[...new Set(t.flatMap(m=>m.key?[m.key]:[]))];if(t.length<2||s.length===0)continue;const r=t.find(m=>m.key&&m.tag==="MaxSize"&&m.id===`${m.groupId}.MaxSize`),h=r?`move group ${r.groupId} to another position (its MaxSize takes the group's Sequence; #66 picks a free one automatically)`:"give each step its own Sequence";i("scaling-collision",s,`Scaling of tab ${e}: ${t.map(m=>`${m.tag} ${m.id}`).join(" and ")} have the same Sequence ${a} — Unified Interface then drops every custom control of the table; ${h}`,t.find(m=>m.key)?.id)}}for(const e of U){const o=C.get(e.groupId),n=o?O.get(o):void 0;!n?.length||n.includes(e.size)||i("scaling-size",e.key??[],`${e.tag} ${e.id} has Size "${e.size}", which isn't a layout of template ${o} used by group ${e.groupId} (${n.join(", ")})`,e.id,!0)}const z=new Set(c.known?.elementIds??[]),k=new Map;for(const{key:e,el:o}of u){if(!(o.getAttribute("Location")??"").endsWith("._children"))continue;const n=p(o).find(t=>t.tagName==="CommandUIDefinition"),a=n?p(n)[0]:void 0;if(!(!a||a.tagName==="MaxSize"||a.tagName==="Scale"))for(const t of T(a)){const s=t.getAttribute("Id");if(!s||t.closest("Scaling"))continue;const r=k.get(s)??[];r.includes(e)||k.set(s,[...r,e])}}for(const[e,o]of k)o.length>1?i("duplicate-id",o,`Id ${e} is added by more than one CustomAction (${o.map(n=>n.replace(/^customActions:ca:/,"")).join(", ")})`,e):f.has(o[0])&&z.has(e)&&i("duplicate-id",o,`Id ${e} is added as a new element, but the ribbon already has an element with this id`,e);if(c.places){const{entityLogicalName:e,tabByCollection:o}=c.places,n=new Set(["Mscrm.Tabs",`Mscrm.SubGrid.${e}.ContextualTabs`]);for(const{key:a,el:t}of u){const s=t.getAttribute("Location")??"",r=/^(.+)\._children$/.exec(s)?.[1];if(!r||H.test(s)||!$(a))continue;const h=p(t).find(M=>M.tagName==="CommandUIDefinition"),m=h?p(h)[0]:void 0,D=m?.getAttribute("Id")??"";if(!m||!D||!(he.has(m.tagName)||x.has(m.tagName)))continue;const q=r.split("{!EntityLogicalName}").join(e),P=o[q];if(P!==void 0){Z(P)&&i("orphan-location",a,`${m.tagName} ${D} is added to ${r}, on the tab ${P}: Unified Interface doesn't show that tab and the ribbon doesn't return what is added there, so it won't show anywhere — add it to the table's main tab instead`,D,!0);continue}const G=M=>M.replace(/\.(Controls|Groups)$/,"");n.has(q)||[r,q,G(r),G(q)].some(M=>k.has(M))||i("orphan-location",a,`${m.tagName} ${D} is added at ${s}, but this table's ribbon has no ${r} — it won't show anywhere (check the Location, or move it to an existing group)`,D,!0)}}const _=c.publisherPrefix?.trim().toLowerCase();if(_&&f.size>0){const e=new Set([...z,...c.known?.commandIds??[],...c.known?.enableRuleIds??[],...c.known?.displayRuleIds??[]]),o=t=>{const s=t.split(".");for(let r=s.length;r>0;r--)if(e.has(s.slice(0,r).join(".")))return!0;return!1},n=t=>{const s=t.toLowerCase();return s.startsWith(`${_}.`)||s.startsWith(`${_}_`)},a=new Set;for(const{part:t,key:s,el:r}of d)if(!(!f.has(s)||t==="templates"||t==="tabDisplayRules"))for(const h of T(r)){if(h!==r&&h.closest("Actions, EnableRules, DisplayRules, EnableRule, DisplayRule"))continue;const m=h.getAttribute("Id")??h.getAttribute("HideActionId");!m||a.has(m)||n(m)||o(m)||(a.add(m),w.push({severity:"warning",code:"id-prefix",message:`${h.tagName} id ${m} doesn't start with the publisher prefix "${_}." — ids without it can collide with other solutions`,elementId:m}))}}return w}export{ye as a,we as v,Ae as w};
@@ -1 +1 @@
1
- import{l as e}from"./monaco-BLZnQb2P.js";const t={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{offSide:!0},onEnterRules:[{beforeText:/:\s*$/,action:{indentAction:e.IndentAction.Indent}}]},o={tokenPostfix:".yaml",brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.square",open:"[",close:"]"}],keywords:["true","True","TRUE","false","False","FALSE","null","Null","Null","~"],numberInteger:/(?:0|[+-]?[0-9]+)/,numberFloat:/(?:0|[+-]?[0-9]+)(?:\.[0-9]+)?(?:e[-+][1-9][0-9]*)?/,numberOctal:/0o[0-7]+/,numberHex:/0x[0-9a-fA-F]+/,numberInfinity:/[+-]?\.(?:inf|Inf|INF)/,numberNaN:/\.(?:nan|Nan|NAN)/,numberDate:/\d{4}-\d\d-\d\d([Tt ]\d\d:\d\d:\d\d(\.\d+)?(( ?[+-]\d\d?(:\d\d)?)|Z)?)?/,escapes:/\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,tokenizer:{root:[{include:"@whitespace"},{include:"@comment"},[/%[^ ]+.*$/,"meta.directive"],[/---/,"operators.directivesEnd"],[/\.{3}/,"operators.documentEnd"],[/[-?:](?= )/,"operators"],{include:"@anchor"},{include:"@tagHandle"},{include:"@flowCollections"},{include:"@blockStyle"},[/@numberInteger(?![ \t]*\S+)/,"number"],[/@numberFloat(?![ \t]*\S+)/,"number.float"],[/@numberOctal(?![ \t]*\S+)/,"number.octal"],[/@numberHex(?![ \t]*\S+)/,"number.hex"],[/@numberInfinity(?![ \t]*\S+)/,"number.infinity"],[/@numberNaN(?![ \t]*\S+)/,"number.nan"],[/@numberDate(?![ \t]*\S+)/,"number.date"],[/(".*?"|'.*?'|[^#'"]*?)([ \t]*)(:)( |$)/,["type","white","operators","white"]],{include:"@flowScalars"},[/.+?(?=(\s+#|$))/,{cases:{"@keywords":"keyword","@default":"string"}}]],object:[{include:"@whitespace"},{include:"@comment"},[/\}/,"@brackets","@pop"],[/,/,"delimiter.comma"],[/:(?= )/,"operators"],[/(?:".*?"|'.*?'|[^,\{\[]+?)(?=: )/,"type"],{include:"@flowCollections"},{include:"@flowScalars"},{include:"@tagHandle"},{include:"@anchor"},{include:"@flowNumber"},[/[^\},]+/,{cases:{"@keywords":"keyword","@default":"string"}}]],array:[{include:"@whitespace"},{include:"@comment"},[/\]/,"@brackets","@pop"],[/,/,"delimiter.comma"],{include:"@flowCollections"},{include:"@flowScalars"},{include:"@tagHandle"},{include:"@anchor"},{include:"@flowNumber"},[/[^\],]+/,{cases:{"@keywords":"keyword","@default":"string"}}]],multiString:[[/^( +).+$/,"string","@multiStringContinued.$1"]],multiStringContinued:[[/^( *).+$/,{cases:{"$1==$S2":"string","@default":{token:"@rematch",next:"@popall"}}}]],whitespace:[[/[ \t\r\n]+/,"white"]],comment:[[/#.*$/,"comment"]],flowCollections:[[/\[/,"@brackets","@array"],[/\{/,"@brackets","@object"]],flowScalars:[[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/'[^']*'/,"string"],[/"/,"string","@doubleQuotedString"]],doubleQuotedString:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],blockStyle:[[/[>|][0-9]*[+-]?$/,"operators","@multiString"]],flowNumber:[[/@numberInteger(?=[ \t]*[,\]\}])/,"number"],[/@numberFloat(?=[ \t]*[,\]\}])/,"number.float"],[/@numberOctal(?=[ \t]*[,\]\}])/,"number.octal"],[/@numberHex(?=[ \t]*[,\]\}])/,"number.hex"],[/@numberInfinity(?=[ \t]*[,\]\}])/,"number.infinity"],[/@numberNaN(?=[ \t]*[,\]\}])/,"number.nan"],[/@numberDate(?=[ \t]*[,\]\}])/,"number.date"]],tagHandle:[[/\![^ ]*/,"tag"]],anchor:[[/[&*][^ ]+/,"namespace"]]}};export{t as conf,o as language};
1
+ import{d as e}from"./monaco-Bx8A1Vm1.js";const t={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],folding:{offSide:!0},onEnterRules:[{beforeText:/:\s*$/,action:{indentAction:e.IndentAction.Indent}}]},o={tokenPostfix:".yaml",brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.square",open:"[",close:"]"}],keywords:["true","True","TRUE","false","False","FALSE","null","Null","Null","~"],numberInteger:/(?:0|[+-]?[0-9]+)/,numberFloat:/(?:0|[+-]?[0-9]+)(?:\.[0-9]+)?(?:e[-+][1-9][0-9]*)?/,numberOctal:/0o[0-7]+/,numberHex:/0x[0-9a-fA-F]+/,numberInfinity:/[+-]?\.(?:inf|Inf|INF)/,numberNaN:/\.(?:nan|Nan|NAN)/,numberDate:/\d{4}-\d\d-\d\d([Tt ]\d\d:\d\d:\d\d(\.\d+)?(( ?[+-]\d\d?(:\d\d)?)|Z)?)?/,escapes:/\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,tokenizer:{root:[{include:"@whitespace"},{include:"@comment"},[/%[^ ]+.*$/,"meta.directive"],[/---/,"operators.directivesEnd"],[/\.{3}/,"operators.documentEnd"],[/[-?:](?= )/,"operators"],{include:"@anchor"},{include:"@tagHandle"},{include:"@flowCollections"},{include:"@blockStyle"},[/@numberInteger(?![ \t]*\S+)/,"number"],[/@numberFloat(?![ \t]*\S+)/,"number.float"],[/@numberOctal(?![ \t]*\S+)/,"number.octal"],[/@numberHex(?![ \t]*\S+)/,"number.hex"],[/@numberInfinity(?![ \t]*\S+)/,"number.infinity"],[/@numberNaN(?![ \t]*\S+)/,"number.nan"],[/@numberDate(?![ \t]*\S+)/,"number.date"],[/(".*?"|'.*?'|[^#'"]*?)([ \t]*)(:)( |$)/,["type","white","operators","white"]],{include:"@flowScalars"},[/.+?(?=(\s+#|$))/,{cases:{"@keywords":"keyword","@default":"string"}}]],object:[{include:"@whitespace"},{include:"@comment"},[/\}/,"@brackets","@pop"],[/,/,"delimiter.comma"],[/:(?= )/,"operators"],[/(?:".*?"|'.*?'|[^,\{\[]+?)(?=: )/,"type"],{include:"@flowCollections"},{include:"@flowScalars"},{include:"@tagHandle"},{include:"@anchor"},{include:"@flowNumber"},[/[^\},]+/,{cases:{"@keywords":"keyword","@default":"string"}}]],array:[{include:"@whitespace"},{include:"@comment"},[/\]/,"@brackets","@pop"],[/,/,"delimiter.comma"],{include:"@flowCollections"},{include:"@flowScalars"},{include:"@tagHandle"},{include:"@anchor"},{include:"@flowNumber"},[/[^\],]+/,{cases:{"@keywords":"keyword","@default":"string"}}]],multiString:[[/^( +).+$/,"string","@multiStringContinued.$1"]],multiStringContinued:[[/^( *).+$/,{cases:{"$1==$S2":"string","@default":{token:"@rematch",next:"@popall"}}}]],whitespace:[[/[ \t\r\n]+/,"white"]],comment:[[/#.*$/,"comment"]],flowCollections:[[/\[/,"@brackets","@array"],[/\{/,"@brackets","@object"]],flowScalars:[[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/'[^']*'/,"string"],[/"/,"string","@doubleQuotedString"]],doubleQuotedString:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],blockStyle:[[/[>|][0-9]*[+-]?$/,"operators","@multiString"]],flowNumber:[[/@numberInteger(?=[ \t]*[,\]\}])/,"number"],[/@numberFloat(?=[ \t]*[,\]\}])/,"number.float"],[/@numberOctal(?=[ \t]*[,\]\}])/,"number.octal"],[/@numberHex(?=[ \t]*[,\]\}])/,"number.hex"],[/@numberInfinity(?=[ \t]*[,\]\}])/,"number.infinity"],[/@numberNaN(?=[ \t]*[,\]\}])/,"number.nan"],[/@numberDate(?=[ \t]*[,\]\}])/,"number.date"]],tagHandle:[[/\![^ ]*/,"tag"]],anchor:[[/[&*][^ ]+/,"namespace"]]}};export{t as conf,o as language};
@@ -0,0 +1,16 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="4 8 56 48" width="56" height="48">
2
+ <!-- Variant K — "Clean hex split" / CBS
3
+ Same chassis as the sibling studios (FXS, DRS); tool glyph is a
4
+ command bar: a rounded bar holding three command buttons, with the
5
+ middle one selected. -->
6
+
7
+ <path d="M 18 8 L 46 8 L 60 32 L 46 56 L 18 56 L 4 32 Z" fill="#0E5A9C"/>
8
+ <polygon points="46,8 60,32 46,56 18,56" fill="#2B8FD9"/>
9
+
10
+ <!-- Tool glyph — command bar with three buttons, in white -->
11
+ <rect x="14" y="23" width="36" height="18" rx="3.5" stroke="#fff" stroke-width="2.5" fill="none"/>
12
+ <rect x="19" y="28.5" width="7" height="7" rx="1.5" fill="#fff"/>
13
+ <rect x="28.5" y="28.5" width="7" height="7" rx="1.5" fill="#fff"/>
14
+ <rect x="38" y="28.5" width="7" height="7" rx="1.5" fill="#fff"/>
15
+ <line x1="28" y1="45.5" x2="36" y2="45.5" stroke="#fff" stroke-width="2.5" stroke-linecap="round"/>
16
+ </svg>
package/dist/index.html CHANGED
@@ -1,18 +1,24 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Command Bar Studio</title>
7
- <script type="module" crossorigin src="/assets/index-DjHxPFpB.js"></script>
8
- <link rel="modulepreload" crossorigin href="/assets/monaco-BLZnQb2P.js">
9
- <link rel="modulepreload" crossorigin href="/assets/fluent-icons-DiKr_qRE.js">
10
- <link rel="modulepreload" crossorigin href="/assets/fluent-ui-kUA2U4Gr.js">
11
- <link rel="modulepreload" crossorigin href="/assets/dnd-DHB99ZH7.js">
12
- <link rel="stylesheet" crossorigin href="/assets/monaco-Dvl_Svmm.css">
13
- <link rel="stylesheet" crossorigin href="/assets/index-D9lerlVA.css">
14
- </head>
15
- <body>
16
- <div id="root"></div>
17
- </body>
18
- </html>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Command Bar Studio</title>
7
+ <script type="module" crossorigin src="./assets/index-Bu7BlRFk.js"></script>
8
+ <link rel="modulepreload" crossorigin href="./assets/monaco-Bx8A1Vm1.js">
9
+ <link rel="modulepreload" crossorigin href="./assets/fluent-icons-DxKNRZ1A.js">
10
+ <link rel="modulepreload" crossorigin href="./assets/fluent-ui-D7EtYwEg.js">
11
+ <link rel="modulepreload" crossorigin href="./assets/dnd-fsSwRnQv.js">
12
+ <link rel="stylesheet" crossorigin href="./assets/monaco-Dprb6f6S.css">
13
+ <link rel="stylesheet" crossorigin href="./assets/index-D9lerlVA.css">
14
+ </head>
15
+ <body>
16
+ <div id="root">
17
+ <p style="font-family: 'Segoe UI', system-ui, sans-serif; padding: 24px; max-width: 720px">
18
+ Loading Command Bar Studio… If this message stays, the tool couldn't start: use Power Platform
19
+ ToolBox 1.2.7 or later (desktop app or VS Code extension), and report it at
20
+ github.com/mohsinonxrm/pptb-mxrm-commandbar-studio/issues.
21
+ </p>
22
+ </div>
23
+ </body>
24
+ </html>
package/index.html CHANGED
@@ -1,12 +1,18 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Command Bar Studio</title>
7
- </head>
8
- <body>
9
- <div id="root"></div>
10
- <script type="module" src="/src/main.tsx"></script>
11
- </body>
12
- </html>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Command Bar Studio</title>
7
+ </head>
8
+ <body>
9
+ <div id="root">
10
+ <p style="font-family: 'Segoe UI', system-ui, sans-serif; padding: 24px; max-width: 720px">
11
+ Loading Command Bar Studio… If this message stays, the tool couldn't start: use Power Platform
12
+ ToolBox 1.2.7 or later (desktop app or VS Code extension), and report it at
13
+ github.com/mohsinonxrm/pptb-mxrm-commandbar-studio/issues.
14
+ </p>
15
+ </div>
16
+ <script type="module" src="/src/main.tsx"></script>
17
+ </body>
18
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohsinonxrm/pptb-commandbar-studio",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "displayName": "Command Bar Studio",
5
5
  "description": "Visual designer for Dataverse classic ribbon / command bar customizations — the spiritual successor to Ribbon Workbench, built for Power Platform ToolBox",
6
6
  "author": "Mohsin On xRM",
@@ -23,7 +23,7 @@
23
23
  "microsoft"
24
24
  ],
25
25
  "main": "index.html",
26
- "icon": "icons/command-bar-studio.svg",
26
+ "icon": "icons/icon.svg",
27
27
  "repository": {
28
28
  "type": "git",
29
29
  "url": "git+https://github.com/mohsinonxrm/pptb-mxrm-commandbar-studio.git"
@@ -35,8 +35,8 @@
35
35
  }
36
36
  ],
37
37
  "features": {
38
- "multiConnection": "none",
39
- "minAPI": "1.2.0"
38
+ "connections": 1,
39
+ "minAPI": "1.2.7"
40
40
  },
41
41
  "bugs": {
42
42
  "url": "https://github.com/mohsinonxrm/pptb-mxrm-commandbar-studio/issues"
@@ -48,32 +48,29 @@
48
48
  },
49
49
  "files": [
50
50
  "dist",
51
- "icons",
52
51
  "index.html",
53
52
  "LICENSE",
54
53
  "README.md",
55
54
  "CHANGELOG.md",
56
- "SECURITY.md",
57
- "npm-shrinkwrap.json"
55
+ "SECURITY.md"
58
56
  ],
59
57
  "type": "module",
58
+ "engines": {
59
+ "node": ">=22"
60
+ },
60
61
  "scripts": {
61
62
  "dev": "vite",
63
+ "dev:harness": "vite --open /dev/harness/",
62
64
  "build": "tsc -b && vite build",
63
65
  "preview": "vite preview",
64
- "typecheck": "tsc --noEmit",
65
- "lint": "eslint src --max-warnings 0",
66
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.node.json --noEmit && tsc -p tsconfig.harness.json",
67
+ "lint": "eslint . --max-warnings 0",
66
68
  "test": "vitest run",
67
69
  "test:watch": "vitest",
68
- "test:coverage": "vitest run --coverage",
69
- "test:ui": "vitest --ui",
70
70
  "validate": "pptb-validate",
71
- "finalize-package": "npm run validate && npm run build && npm shrinkwrap",
72
- "release": "release-it",
73
- "release:dry": "release-it --dry-run",
74
- "release:pre": "release-it --preRelease=beta",
75
- "analyze": "vite build && start dist/stats.html",
76
- "prepare": "husky"
71
+ "format": "prettier --write .",
72
+ "format:check": "prettier --check .",
73
+ "version-badge": "node .github/scripts/version-badge.mjs"
77
74
  },
78
75
  "dependencies": {
79
76
  "@dnd-kit/core": "^6.3.1",
@@ -89,33 +86,22 @@
89
86
  "zustand": "^5.0.5"
90
87
  },
91
88
  "devDependencies": {
92
- "@commitlint/cli": "^19.8.1",
93
- "@commitlint/config-conventional": "^19.8.1",
94
89
  "@eslint/js": "^9.25.0",
95
- "@pptb/types": "^1.2.3",
96
- "@release-it/conventional-changelog": "^10.0.6",
97
- "@testing-library/jest-dom": "^6.6.3",
98
- "@testing-library/react": "^16.3.0",
99
- "@testing-library/user-event": "^14.6.1",
90
+ "@pptb/types": "1.2.7",
91
+ "@types/node": "^22.20.5",
100
92
  "@types/react": "^18.3.21",
101
93
  "@types/react-dom": "^18.3.5",
102
- "@typescript-eslint/eslint-plugin": "^8.30.1",
103
- "@typescript-eslint/parser": "^8.30.1",
104
94
  "@vitejs/plugin-react": "^5.2.0",
105
- "@vitest/coverage-v8": "^3.1.2",
106
- "@vitest/ui": "^3.1.2",
107
95
  "eslint": "^9.25.0",
108
96
  "eslint-plugin-jsx-a11y": "^6.10.2",
109
97
  "eslint-plugin-react-hooks": "^5.2.0",
110
98
  "eslint-plugin-react-refresh": "^0.4.19",
111
- "eslint-plugin-vitest": "^0.5.4",
112
99
  "globals": "^16.0.0",
113
- "husky": "^9.1.7",
114
100
  "jsdom": "^26.1.0",
115
101
  "monaco-editor": "^0.55.1",
116
- "release-it": "^19.2.4",
117
- "rollup-plugin-visualizer": "^5.14.0",
102
+ "prettier": "^3.9.10",
118
103
  "typescript": "^5.8.3",
104
+ "typescript-eslint": "^8.71.2",
119
105
  "vite": "^7.3.3",
120
106
  "vitest": "^3.1.2"
121
107
  }
@@ -1,29 +0,0 @@
1
- import{cw as i,cx as Pe}from"./fluent-icons-DiKr_qRE.js";import{r as S,b as pe}from"./monaco-BLZnQb2P.js";import{d as _,h as X,z as je,s as ee,i as se,u as I}from"./index-DjHxPFpB.js";import{g as Ce,w as $e,e as $,s as me}from"./xmlGenerator-DEaVrfZJ.js";import{d as ve,h as Ie,i as Re,f as ke,g as Le,u as q,w as O,a1 as N,Q as ie,a as T,C as oe,F as te,n as ze,O as be,I as Xe,J as De,R as Ee,B as Me,A as Te,e as Ue}from"./fluent-ui-kUA2U4Gr.js";import"./dnd-DHB99ZH7.js";const x=window.dataverseAPI;function de(e){const t=e.data?.progress;return!!(typeof t=="object"&&t!==null&&t.completed===!0||typeof e.progress=="number"&&e.progress>=100||typeof t=="number"&&t>=100||e.completedon||e.data?.completedon||e.statuscode===30)}async function he(e,t){const n=_.getState();t?.("Generating RibbonDiffXml…"),n.logInfo("publish",`Generating RibbonDiffXml for ${e.entityLogicalName}.`);const b=Ce({current:e.current,baseline:e.baseline,commands:e.commands,enableRules:e.enableRules,displayRules:e.displayRules,locLabels:e.locLabels,entityLogicalName:e.entityLogicalName,location:e.current.location}),h=X.getState().formRibbonScope,m=X.getState().selectedFormId,c=e.current.location==="Application"?"application":e.current.location==="Form"&&h==="form"?"form":"entity",R=$e(b,e.entityLogicalName,c,c==="form"?m:void 0),g=[];if(c==="entity"&&e.entityLogicalName?g.push({type:1,schemaName:e.entityLogicalName,behavior:2}):c==="form"&&e.entityLogicalName&&m&&(g.push({type:1,schemaName:e.entityLogicalName,behavior:2}),g.push({type:60,id:m,behavior:0})),c==="application"&&e.ribbonCustomizationIds?.length)for(const p of e.ribbonCustomizationIds)g.push({type:50,id:p,behavior:0});const w=Fe({uniqueName:e.solutionUniqueName,publisherUniqueName:e.publisherUniqueName,publisherName:e.publisherName,publisherPrefix:e.publisherPrefix,version:e.solutionVersion,rootComponents:g});t?.("Packaging solution ZIP…"),n.logInfo("publish","Packaging solution ZIP...");const l=je({"customizations.xml":ee(R),"solution.xml":ee(w),"[Content_Types].xml":ee('<?xml version="1.0" encoding="utf-8"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="xml" ContentType="application/xml"/></Types>')});let P="";for(let p=0;p<l.length;p++)P+=String.fromCharCode(l[p]);const a=btoa(P);t?.("Importing solution…"),n.logInfo("publish","Importing solution via deploySolution...");const u=typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`${Date.now()}-${Math.random().toString(16).slice(2)}-${Math.random().toString(16).slice(2)}`;n.logInfo("publish",`Import job id: ${u}`),await x.deploySolution(a,{importJobId:u,overwriteUnmanagedCustomizations:!0,publishWorkflows:!1}),t?.("Waiting for import to complete…"),n.logInfo("publish",`Polling import job ${u}...`);const f=150,j=2e3;let k=await x.getImportJobStatus(u),v=0;for(;!de(k)&&v<f;)await new Promise(p=>setTimeout(p,j)),k=await x.getImportJobStatus(u),v++,v%15===0&&t?.(`Still importing… (${v*2}s elapsed)`);if(!de(k)){const p=Math.round(f*j/1e3);throw n.logError("publish",`Solution import did not complete within ${p}s. Check Solutions › History in maker.powerapps.com for job ${u} — the import may still succeed there.`),new Error(`Solution import did not signal completion within ${p} seconds. Check Solutions › History for job ${u}.`)}if(e.publishCustomizations!==!1){t?.("Publishing customizations…"),n.logInfo("publish","Publishing customizations...");const p=new Date;e.entityLogicalName&&e.entityLogicalName!=="{!EntityLogicalName}"?await x.publishCustomizations(e.entityLogicalName):await x.publishCustomizations(),await Ve(e.entityLogicalName,p,n,t)}t?.("Published successfully!"),n.logInfo("publish","Publish completed successfully.")}async function Ve(e,t,n,b){const c=e&&e!=="{!EntityLogicalName}"?`entityname eq '${e}'`:null,g=`ribbonmetadatasettoprocess?$select=entityname,processedon,completedon,exceptionmessage,retrycount,status&$orderby=createdon desc&$top=10&$filter=createdon gt ${t.toISOString().replace(/\.\d+Z$/,"Z")}`+(c?` and (${c})`:"");for(let w=0;w<15;w++){await new Promise(l=>setTimeout(l,2e3));try{const l=await x.queryData(g),P=Array.isArray(l)?l:Array.isArray(l?.value)?l.value:[];if(P.length===0)continue;const a=P.find(f=>f.exceptionmessage);if(a){const j=`Ribbon-metadata compile failed for ${a.entityname||e}: `+a.exceptionmessage;throw n.logError("publish",j),b?.(`⚠ ${j}`),new Error(j)}const u=P.find(f=>f.completedon||f.processedon||f.status===4);if(u){const f=u.entityname||e;n.logInfo("publish",`Ribbon metadata compiled successfully for ${f}.`);return}w===Math.floor(15/2)&&(b?.("Waiting for ribbon-metadata compilation…"),n.logInfo("publish","Ribbon metadata job found; waiting for completion…"))}catch(l){if(l instanceof Error&&l.message.includes("Ribbon-metadata compile failed"))throw l;n.logWarn("publish",`Could not read ribbonmetadatasettoprocess (${l instanceof Error?l.message:String(l)}). Ribbon metadata verification skipped.`);return}}n.logInfo("publish","Ribbon metadata job not observed within 30 s. The publish appears complete — open the entity to confirm your changes are live.")}function qe(e){const t=e.entityLogicalNames.map(b=>`<entity>${$(b)}</entity>`).join(""),n=e.publishDependencies?"<nodes/><securityroles/><settings/><workflows/><templates/><plugins/><sdkmessageprocessingsteps/><serviceendpoints/><webresources/>":"<nodes/>";return`<importexportxml><entities>${t}</entities>${n}</importexportxml>`}async function Oe(e,t){const n=_.getState(),b=e.entityLogicalNames.filter(Boolean);if(b.length===0){e.includeApplicationRibbon&&(t?.("Publishing all customizations..."),await x.publishCustomizations());return}const h=qe({entityLogicalNames:b,publishDependencies:e.publishDependencies});t?.("Publishing selected components with PublishXml..."),n.logInfo("publish",`PublishXml request for ${b.length} table(s).`);try{await x.execute({operationName:"PublishXml",operationType:"action",parameters:{ParameterXml:h}}),e.includeApplicationRibbon&&(t?.("Publishing application ribbon..."),await x.publishCustomizations()),n.logInfo("publish","PublishXml completed successfully.")}catch(m){n.logWarn("publish",`PublishXml failed, falling back to publishCustomizations(): ${m instanceof Error?m.message:String(m)}`);for(const c of b)t?.(`Fallback publish for ${c}...`),await x.publishCustomizations(c);e.includeApplicationRibbon&&(t?.("Fallback publish for application ribbon..."),await x.publishCustomizations())}}async function Be(e,t){const n=_.getState(),b=2e3,h=600*1e3;e?.("Starting asynchronous publish (PublishAllXmlAsync)..."),n.logInfo("publish","Calling PublishAllXmlAsync action.");const c=(await x.execute({operationName:"PublishAllXmlAsync",operationType:"action"}))?.AsyncOperationId;if(!c)throw new Error("PublishAllXmlAsync did not return AsyncOperationId.");n.logInfo("publish",`PublishAllXmlAsync job id: ${c}`),e?.("Async publish job started. Waiting for completion...");const R=Date.now();let g=0,w;for(;Date.now()-R<h;){g+=1;const l=await x.retrieve("asyncoperation",c,["asyncoperationid","statecode","statuscode","name","message","friendlymessage","completedon"]);if(w=l.statuscode,l.statecode===3||!!l.completedon){if(typeof l.statuscode=="number"&&l.statuscode!==30){const a=l.friendlymessage||l.message||`statuscode=${l.statuscode}`;throw new Error(`Asynchronous publish failed: ${a}`)}return e?.("Asynchronous publish completed successfully."),n.logInfo("publish",`PublishAllXmlAsync completed in ${g} poll(s).`),{asyncOperationId:c,statusCode:l.statuscode}}e?.(`Waiting for async publish job... (poll ${g})`),await new Promise(a=>setTimeout(a,b))}throw new Error(`Asynchronous publish timed out after ${Math.round(h/1e3)} seconds (last status: ${w??"unknown"}).`)}function Fe(e){const t=e.publisherUniqueName?.trim()||"DefaultPublisher",n=e.publisherName?.trim()||t,b=e.publisherPrefix?.trim()||"new",h=e.rootComponents.length===0?"<RootComponents/>":`<RootComponents>
2
- ${e.rootComponents.map(m=>{const c=[`type="${m.type}"`];return m.schemaName&&c.push(`schemaName="${$(m.schemaName)}"`),m.id&&c.push(`id="{${$(m.id)}}"`),c.push(`behavior="${m.behavior}"`),`<RootComponent ${c.join(" ")} />`}).join(`
3
- `)}
4
- </RootComponents>`;return`<?xml version="1.0" encoding="utf-8"?>
5
- <ImportExportXml version="9.1.0.0" SolutionPackageVersion="9.1" languagecode="1033" generatedBy="CommandBarStudio">
6
- <SolutionManifest>
7
- <UniqueName>${$(e.uniqueName)}</UniqueName>
8
- <LocalizedNames>
9
- <LocalizedName description="${$(e.uniqueName)}" languagecode="1033"/>
10
- </LocalizedNames>
11
- <Descriptions/>
12
- <Version>${$(e.version)}</Version>
13
- <Managed>0</Managed>
14
- <Publisher>
15
- <UniqueName>${$(t)}</UniqueName>
16
- <LocalizedNames>
17
- <LocalizedName description="${$(n)}" languagecode="1033"/>
18
- </LocalizedNames>
19
- <Descriptions/>
20
- <EMailAddress/>
21
- <SupportingWebsiteUrl/>
22
- <CustomizationPrefix>${$(b)}</CustomizationPrefix>
23
- <CustomizationOptionValuePrefix>10000</CustomizationOptionValuePrefix>
24
- <Addresses/>
25
- </Publisher>
26
- ${h}
27
- <MissingDependencies/>
28
- </SolutionManifest>
29
- </ImportExportXml>`}const _e=Pe({content:{display:"flex",flexDirection:"column",gap:N.spacingVerticalM},entityList:{display:"flex",flexDirection:"column",gap:N.spacingVerticalXS,maxHeight:"240px",overflowY:"auto",border:`1px solid ${N.colorNeutralStroke2}`,borderRadius:N.borderRadiusMedium,padding:N.spacingVerticalXS},progressList:{display:"flex",flexDirection:"column",gap:N.spacingVerticalXS},progressRow:{display:"flex",alignItems:"center",gap:N.spacingHorizontalS}}),Qe=()=>{const e=_e(),t=se(s=>s.bulkPublishOpen),n=se(s=>s.closeBulkPublish),b=se(s=>s.openXmlDrawer),h=I(s=>s.ribbons),m=I(s=>s.baseline),c=I(s=>s.commands),R=I(s=>s.displayRules),g=I(s=>s.enableRules),w=I(s=>s.locLabels),l=I(s=>s.markPublished),P=I(s=>s.mutationsSincePublish),a=X(s=>s.activeSolution),u=X(s=>s.activeEntity),f=X(s=>s.entities),j=X(s=>s.publisherPrefix),k=X(s=>s.solutionRibbonComponentIds),v=Array.isArray(k)&&k.length>0,[p,W]=S.useState(u?[u.logicalName]:[]),[C,ge]=S.useState(!1),[L,H]=S.useState(!1),[fe,A]=S.useState({}),[B,ne]=S.useState(!1),[U,ye]=S.useState(!1),[le,xe]=S.useState(!0),[J,Se]=S.useState("targeted"),[ae,D]=S.useState(""),[Ne,we]=S.useState(""),[V,re]=S.useState(a?.version??"1.0.0.0"),[F,Z]=S.useState([]),G=pe.useMemo(()=>{const o=(V||a?.version||"1.0.0.0").split(".").map(y=>Number.parseInt(y,10)||0);for(;o.length<4;)o.push(0);return o[3]+=1,o.slice(0,4).join(".")},[a?.version,V]);pe.useEffect(()=>{re(a?.version??"1.0.0.0")},[a?.version]);const Ae=s=>{W(o=>o.includes(s)?o.filter(y=>y!==s):[...o,s])},Y=s=>{A(o=>{const y={...o};for(const E of p)y[E]=s;return C&&(y.Application=s),y})},ce=async s=>{if(!a)return;H(!0),D(""),Z([]);const o={};p.forEach(d=>o[d]="pending"),C&&(o.Application="pending"),A(o);let y=!1;const E=[],M=_.getState(),Q=d=>d instanceof Error?d.message:String(d);if(u&&p.includes(u.logicalName)){A(r=>({...r,[u.logicalName]:"publishing"}));const d=["HomepageGrid","SubGrid","Form"].filter(r=>me(h[r],m[r]).hasAnyChange);if(d.length===0)M.logInfo("publish",`Entity ribbon publish skipped (${u.logicalName}) — no changes vs. baseline.`),A(r=>({...r,[u.logicalName]:"success"}));else try{for(const r of d)M.logInfo("publish",`Publishing ${r} ribbon for ${u.logicalName}…`),await he({current:h[r],baseline:m[r],commands:c,displayRules:R,enableRules:g,locLabels:w,entityLogicalName:u.logicalName,solutionUniqueName:a.uniqueName,publisherUniqueName:a.publisherUniqueName,publisherName:a.publisherName,publisherPrefix:a.publisherPrefix||j,solutionVersion:U?G:V,publishCustomizations:!1},z=>D(z));A(r=>({...r,[u.logicalName]:"success"}))}catch(r){y=!0;const z=Q(r);E.push({scope:u.logicalName,message:z}),M.logError("publish",`Entity ribbon publish failed (${u.logicalName}): ${z}`),A(K=>({...K,[u.logicalName]:"error"}))}}if(C)if(!me(h.Application,m.Application).hasAnyChange)M.logInfo("publish","Application ribbon publish skipped — no changes vs. baseline."),A(r=>({...r,Application:"success"}));else{A(r=>({...r,Application:"publishing"}));try{await he({current:h.Application,baseline:m.Application,commands:c,displayRules:R,enableRules:g,locLabels:w,entityLogicalName:"{!EntityLogicalName}",solutionUniqueName:a.uniqueName,publisherUniqueName:a.publisherUniqueName,publisherName:a.publisherName,publisherPrefix:a.publisherPrefix||j,solutionVersion:U?G:V,ribbonCustomizationIds:k??[],publishCustomizations:!1},r=>D(r)),A(r=>({...r,Application:"success"}))}catch(r){y=!0;const z=Q(r);E.push({scope:"Application ribbon",message:z}),M.logError("publish",`Application ribbon publish failed: ${z}`),A(K=>({...K,Application:"error"}))}}if(s==="publish"&&!y)try{Y("publishing"),J==="targeted"?await Oe({entityLogicalNames:p,includeApplicationRibbon:C,publishDependencies:le},d=>D(d)):await Be(d=>D(d)),Y("success"),l()}catch(d){y=!0;const r=Q(d);E.push({scope:"Publish customizations",message:r}),M.logError("publish",`Publish customizations failed: ${r}`),Y("error")}Z(E),ne(!y),H(!1)},ue=()=>{H(!1),A({}),ne(!1),D(""),Z([]),n()};return i.jsx(ve,{open:t,onOpenChange:()=>!L&&ue(),children:i.jsxs(Ie,{style:{maxWidth:"640px",maxHeight:"92vh",display:"flex",flexDirection:"column"},children:[i.jsx(Re,{children:"Publish to Dataverse"}),i.jsxs(ke,{style:{flex:1,minHeight:0,overflow:"hidden"},children:[i.jsx(Le,{style:{overflowY:"auto",maxHeight:"100%"},children:i.jsxs("div",{className:e.content,children:[!a&&i.jsx(q,{intent:"warning",children:i.jsx(O,{children:"No solution selected. Please select a solution first."})}),i.jsx(q,{intent:"info",children:i.jsxs(O,{children:["Publishing typically takes 5-30 seconds per table. Open users will see the updated ribbon on next page load. You have ",i.jsx("strong",{children:P})," ","change(s) since last publish."]})}),F.length>0&&i.jsx(q,{intent:"error",layout:"multiline",children:i.jsxs(O,{children:[i.jsxs("strong",{children:["Publish failed (",F.length," error",F.length!==1?"s":"",")"]}),i.jsx("ul",{style:{margin:`${N.spacingVerticalXS} 0 0`,paddingLeft:20},children:F.map((s,o)=>i.jsxs("li",{style:{fontFamily:N.fontFamilyMonospace},children:[i.jsxs("strong",{children:[s.scope,":"]})," ",s.message]},o))}),i.jsxs("div",{style:{marginTop:N.spacingVerticalS},children:["Full details are in the ",i.jsx("strong",{children:"Console"})," tab of the bottom panel."]})]})}),!L&&!B&&i.jsxs(i.Fragment,{children:[i.jsx(ie,{weight:"semibold",children:"Select tables to publish:"}),i.jsxs("div",{style:{display:"flex",gap:N.spacingHorizontalS},children:[i.jsx(T,{appearance:"subtle",size:"small",onClick:()=>W(f.map(s=>s.logicalName)),children:"Select all"}),i.jsx(T,{appearance:"subtle",size:"small",onClick:()=>W([]),children:"Deselect all"})]}),i.jsx("div",{className:e.entityList,children:f.map(s=>i.jsx(oe,{label:`${s.displayName||s.logicalName} (${s.logicalName})`,checked:p.includes(s.logicalName),onChange:()=>Ae(s.logicalName)},s.logicalName))}),i.jsxs("div",{children:[i.jsx(oe,{label:"Include Application Ribbon",checked:C&&v,disabled:!v,onChange:(s,o)=>ge(o.checked===!0)}),!v&&i.jsxs(ie,{size:100,style:{color:N.colorNeutralForeground3,display:"block",marginLeft:28,marginTop:2},children:["This solution doesn't include the Application Ribbon component. In maker.powerapps.com, open the solution and choose"," ",i.jsx("strong",{children:"Add existing → Application Ribbons"}),", then reload here."]})]}),i.jsx(te,{label:"Publish strategy",children:i.jsxs(ze,{selectedOptions:[J],onOptionSelect:(s,o)=>{(o.optionValue==="targeted"||o.optionValue==="allAsync")&&Se(o.optionValue)},children:[i.jsx(be,{value:"targeted",children:"Targeted publish (PublishXml)"}),i.jsx(be,{value:"allAsync",children:"Async publish all (PublishAllXmlAsync)"})]})}),i.jsx(q,{intent:"info",children:i.jsx(O,{children:J==="targeted"?"Targeted mode publishes selected tables/components using PublishXml.":"Async mode runs PublishAllXmlAsync and tracks the background system job."})}),i.jsx(te,{label:"Solution version",children:i.jsx(Xe,{size:"small",value:U?G:V,onChange:(s,o)=>re(o.value),disabled:U})}),i.jsx(De,{label:"Increment solution version",checked:U,onChange:(s,o)=>ye(o.checked===!0)}),i.jsx(oe,{label:"Publish dependencies (commands, rules, web resources)",checked:le,onChange:(s,o)=>xe(o.checked===!0)}),i.jsx(te,{label:"Publish comment",children:i.jsx(Ee,{resize:"vertical",value:Ne,onChange:(s,o)=>we(o.value)})}),i.jsx(T,{appearance:"subtle",onClick:()=>{b(),n()},children:"View RibbonDiffXml"})]}),(L||B)&&i.jsxs("div",{className:e.progressList,children:[[...p,...C?["Application"]:[]].map(s=>{const o=fe[s]??"pending";return i.jsxs("div",{className:e.progressRow,children:[i.jsx(Me,{appearance:"filled",color:o==="success"?"success":o==="error"?"danger":o==="publishing"?"informative":"subtle",size:"small",children:o}),i.jsx(ie,{children:s}),o==="publishing"&&i.jsx(Te,{thickness:"large",style:{flex:1}})]},s)}),ae&&i.jsx(q,{intent:"info",children:i.jsx(O,{children:ae})})]})]})}),i.jsxs(Ue,{children:[i.jsx(T,{appearance:"secondary",onClick:ue,disabled:L,children:B?"Close":"Cancel"}),!B&&i.jsxs(i.Fragment,{children:[i.jsx(T,{appearance:"secondary",onClick:()=>{ce("save")},disabled:L||p.length===0&&!C||!a,children:"Save only"}),i.jsx(T,{appearance:"primary",onClick:()=>{ce("publish")},disabled:L||p.length===0&&!C||!a,children:L?"Publishing...":`Publish (${p.length+(C?1:0)})`})]})]})]})]})})};export{Qe as BulkPublishModal,Qe as default};
@@ -1 +0,0 @@
1
- import{cw as e,x as Ee,h as Me,aw as z,a as U,cx as xe}from"./fluent-icons-DiKr_qRE.js";import{r as j}from"./monaco-BLZnQb2P.js";import{i as B,u as R,w as De,g as Le}from"./index-DjHxPFpB.js";import{S as V,F as v,I as S,C as We,B as L,a as m,Q as x,a1 as l,x as $e,l as Te,m as _e,k as Ue,K as Ve,T as E,j as ee,u as M,w as D}from"./fluent-ui-kUA2U4Gr.js";import{M as pe}from"./MonacoEditor-DFYisBG6.js";import{l as He,a as Oe,s as Xe}from"./webResourceService-Ck07E3GN.js";import"./dnd-DHB99ZH7.js";const qe=xe({root:{display:"flex",flexDirection:"column",gap:l.spacingVerticalXS},param:{display:"flex",gap:l.spacingHorizontalS,alignItems:"flex-end",padding:l.spacingVerticalXS,border:`1px solid ${l.colorNeutralStroke2}`,borderRadius:l.borderRadiusMedium},typeSelect:{width:"140px",flexShrink:0},valueField:{flex:1},actions:{display:"flex",gap:l.spacingHorizontalXS,flexShrink:0},addButton:{alignSelf:"flex-start"},hint:{color:l.colorNeutralForeground3,fontSize:l.fontSizeBase100}}),Je=[{label:"Context",values:["PrimaryControl","PrimaryControlId","SelectedControl","CommandProperties"]},{label:"Record",values:["PrimaryEntityTypeCode","PrimaryEntityTypeName","FirstPrimaryItemId","PrimaryItemIds"]},{label:"Selection context",values:["SelectedEntityTypeCode","SelectedEntityTypeName","FirstSelectedItemId"]},{label:"Grid selection",values:["SelectedControlSelectedItemCount","SelectedControlSelectedItemIds","SelectedControlSelectedItemReferences","SelectedControlAllItemCount","SelectedControlAllItemIds","SelectedControlAllItemReferences","SelectedControlUnselectedItemCount","SelectedControlUnselectedItemIds","SelectedControlUnselectedItemReferences"]},{label:"Org/User",values:["OrgName","OrgLcid","UserLcid"]}],he=({params:n,onChange:F,urlMode:N=!1})=>{const y=qe(),C=(i,p)=>{const h=[...n];h[i]=p,F(h)},H=i=>{F(n.filter((p,h)=>h!==i))},O=(i,p)=>{const h=[...n],d=i+p;d<0||d>=h.length||([h[i],h[d]]=[h[d],h[i]],F(h))},W=()=>{F([...n,{kind:"CrmParameter",value:"PrimaryControl"}])};return e.jsxs("div",{className:y.root,children:[n.map((i,p)=>e.jsxs("div",{className:y.param,children:[e.jsx("div",{className:y.typeSelect,children:e.jsxs(V,{value:i.kind,onChange:(h,d)=>{const f=d.value;f==="CrmParameter"?C(p,{kind:f,value:"PrimaryControl"}):f==="BoolParameter"?C(p,{kind:f,value:!1}):f==="IntParameter"||f==="DecimalParameter"?C(p,{kind:f,value:0}):C(p,{kind:"StringParameter",value:""})},children:[e.jsx("option",{value:"CrmParameter",children:"CrmParameter"}),e.jsx("option",{value:"StringParameter",children:"String"}),e.jsx("option",{value:"BoolParameter",children:"Boolean"}),e.jsx("option",{value:"IntParameter",children:"Integer"}),e.jsx("option",{value:"DecimalParameter",children:"Decimal"})]})}),N&&e.jsx(v,{label:"Name (querystring key)",style:{width:"130px",flexShrink:0},children:e.jsx(S,{value:i.name??"",onChange:(h,d)=>C(p,{...i,name:d.value||void 0}),placeholder:"key"})}),e.jsx("div",{className:y.valueField,children:i.kind==="CrmParameter"?e.jsx(V,{value:i.value,onChange:(h,d)=>C(p,{...i,value:d.value}),children:Je.map(h=>h.values.map(d=>e.jsx("option",{value:d,children:d},d)))}):i.kind==="BoolParameter"?e.jsx(We,{checked:i.value,onChange:(h,d)=>C(p,{...i,value:d.checked}),label:"true"}):e.jsx(S,{type:i.kind==="StringParameter"?"text":"number",value:String(i.value),onChange:(h,d)=>{const f=i.kind==="StringParameter"?d.value:i.kind==="IntParameter"?parseInt(d.value):parseFloat(d.value);C(p,{...i,value:f})}})}),N&&i.kind==="CrmParameter"&&!i.name&&e.jsx(L,{appearance:"filled",color:"warning",size:"small",title:"Name required for URL actions"}),e.jsxs("div",{className:y.actions,children:[e.jsx(m,{appearance:"subtle",size:"small",icon:e.jsx(Ee,{}),onClick:()=>O(p,-1),disabled:p===0,"aria-label":"Move up"}),e.jsx(m,{appearance:"subtle",size:"small",icon:e.jsx(Me,{}),onClick:()=>O(p,1),disabled:p===n.length-1,"aria-label":"Move down"}),e.jsx(m,{appearance:"subtle",size:"small",icon:e.jsx(z,{}),onClick:()=>H(p),"aria-label":"Remove parameter"})]})]},p)),N&&e.jsxs(x,{className:y.hint,children:["For URL actions, each CrmParameter must have a ",e.jsx("code",{children:"name"})," attribute (querystring key)."]}),e.jsx(m,{className:y.addButton,appearance:"secondary",size:"small",icon:e.jsx(U,{}),onClick:W,children:"Add parameter"})]})},Ge=xe({drawer:{width:"640px",maxWidth:"90vw"},body:{display:"flex",flexDirection:"column",gap:l.spacingVerticalS,padding:l.spacingVerticalM,overflowY:"auto"},actionCard:{border:`1px solid ${l.colorNeutralStroke2}`,borderRadius:l.borderRadiusMedium,padding:l.spacingVerticalM,display:"flex",flexDirection:"column",gap:l.spacingVerticalS},actionHeader:{display:"flex",alignItems:"center",justifyContent:"space-between"},row:{display:"flex",gap:l.spacingHorizontalS,alignItems:"flex-end"},ruleRow:{display:"inline-flex",alignItems:"center",gap:l.spacingHorizontalXS},ruleRemoveBtn:{minWidth:"20px",width:"20px",height:"20px"},ruleChip:{cursor:"pointer"},rulePills:{display:"flex",flexWrap:"wrap",gap:l.spacingHorizontalXS},versionsList:{display:"flex",flexDirection:"column",gap:l.spacingVerticalXS},versionRow:{border:`1px solid ${l.colorNeutralStroke2}`,borderRadius:l.borderRadiusMedium,padding:l.spacingVerticalXS,display:"flex",justifyContent:"space-between",gap:l.spacingHorizontalS},versionMeta:{fontSize:l.fontSizeBase100,color:l.colorNeutralForeground3},securityNote:{fontSize:l.fontSizeBase100},codePanel:{border:`1px solid ${l.colorNeutralStroke2}`,borderRadius:l.borderRadiusMedium,padding:l.spacingVerticalS,display:"flex",flexDirection:"column",gap:l.spacingVerticalS}}),ls=()=>{const n=Ge(),F=B(s=>s.commandEditorOpen),N=B(s=>s.commandEditorId),y=B(s=>s.closeCommandEditor),C=B(s=>s.openCommandEditor),H=B(s=>s.openRuleEditor),O=B(s=>s.openWebResourceBrowser),W=R(s=>s.commands),i=R(s=>s.upsertCommand),p=R(s=>s.renameCommandId),h=R(s=>s.ribbons),d=R(s=>s.displayRules),f=R(s=>s.enableRules),be=R(s=>s.past),je=R(s=>s.upsertEnableRule),ve=R(s=>s.upsertDisplayRule),[P,fe]=j.useState("actions"),[w,se]=j.useState(""),[ge,ae]=j.useState(""),[ye,le]=j.useState(""),[ne,Q]=j.useState(null),[X,re]=j.useState(!1),[ie,q]=j.useState(!1),[Y,I]=j.useState(null),[te,$]=j.useState(""),[Ce,J]=j.useState(!1),[A,oe]=j.useState(null),t=W.find(s=>s.id===N),we=s=>{const a=s.trim();return a.startsWith("$webresource:")?a.slice(13).trim():a},Re=s=>{if(!s)return"";const a=Uint8Array.from(atob(s),u=>u.charCodeAt(0));return new TextDecoder().decode(a)},Se=s=>{const a=new TextEncoder().encode(s);let u="";for(let r=0;r<a.length;r+=1)u+=String.fromCharCode(a[r]);return btoa(u)},Ne=s=>{const a=s.split(".").pop()?.toLowerCase()??"";return{html:1,css:2,js:3,xml:4,png:5,jpg:6,gif:7,xsl:9,ico:10,svg:11,resx:12}[a]??3};j.useEffect(()=>{t&&se(t.id)},[t]);const G=j.useMemo(()=>t?w.trim()?/\s/.test(w)?"Command ID cannot contain whitespace.":w!==t.id&&W.some(s=>s.id.toLowerCase()===w.toLowerCase())?"A command with this ID already exists.":"":"Command ID is required.":"",[w,t,W]),Z=j.useMemo(()=>Object.entries(h).flatMap(([s,a])=>a.tabs.flatMap(u=>u.groups.flatMap(r=>r.buttons.filter(o=>o.commandId===N).map(o=>({location:s,tab:u,group:r,button:o}))))),[h,N]),ce=Z.length;if(!t)return null;const de=async(s,a)=>{const u=t.actions[s];if(!u||u.kind!=="javascript")return;const r=we(u.library);if(!r){I("JavaScript library must be a valid $webresource path."),Q(s),re(a),$(""),oe(null);return}Q(s),re(a),q(!0),I(null),J(!1),oe(r);try{const o=await He(r);if(!o){$(""),I(`Web resource not found: ${r}`);return}const c=await Oe(o.id);$(Re(c))}catch(o){I(o instanceof Error?o.message:"Failed to load web resource content."),$("")}finally{q(!1)}},Pe=async()=>{if(!(!X||ne===null||!A)){q(!0),I(null);try{await Xe(A,Se(te),Ne(A),A.split("/").pop()),J(!1)}catch(s){I(s instanceof Error?s.message:"Failed to save web resource content.")}finally{q(!1)}}},k=s=>{i({...t,...s})},g=(s,a)=>{const u=[...t.actions];u[s]=a,k({actions:u})},K=s=>{k({actions:t.actions.filter((a,u)=>u!==s)})},T=s=>{const a=s==="javascript"?{kind:"javascript",library:"$webresource:",functionName:"",params:[]}:s==="url"?{kind:"url",address:"https://",passParams:!1,params:[]}:s==="powerFx"?{kind:"powerFx",expression:""}:{kind:"customApi",actionName:"",boundParameter:"",inputParameters:[],outputParameters:[]};k({actions:[...t.actions,a]})},Ie=(s,a)=>{const u=ne===a;if(s.kind==="javascript")return e.jsxs("div",{className:n.actionCard,children:[e.jsxs("div",{className:n.actionHeader,children:[e.jsx(L,{appearance:"filled",color:"success",size:"small",children:"JavaScript"}),e.jsx(m,{appearance:"subtle",size:"small",icon:e.jsx(z,{}),onClick:()=>K(a),"aria-label":"Remove action"})]}),e.jsx(v,{label:"Library (Web Resource)",children:e.jsxs("div",{style:{display:"flex",gap:"4px",alignItems:"center"},children:[e.jsx(S,{style:{flex:1},value:s.library,onChange:(r,o)=>g(a,{...s,library:o.value}),placeholder:"$webresource:publisher_/scripts/myfile.js"}),e.jsx(m,{appearance:"subtle",size:"small",onClick:()=>{De.set(r=>{g(a,{...s,library:`$webresource:${r.name}`})}),O()},children:"Browse…"})]})}),e.jsx(v,{label:"Function name",children:e.jsx(S,{value:s.functionName,onChange:(r,o)=>g(a,{...s,functionName:o.value}),placeholder:"MyNamespace.myFunction"})}),e.jsx(M,{intent:"info",children:e.jsx(D,{children:"Read-only function preview and Monaco editing are available in the web resource browser integration path."})}),e.jsx(ee,{children:"Parameters (positional)"}),e.jsx(he,{params:s.params,onChange:r=>g(a,{...s,params:r}),urlMode:!1}),e.jsxs("div",{className:n.row,children:[e.jsx(m,{appearance:"subtle",size:"small",onClick:()=>{de(a,!1)},children:"Function preview"}),e.jsx(m,{appearance:"subtle",size:"small",onClick:()=>{de(a,!0)},children:"Open in Monaco"})]}),u&&e.jsxs("div",{className:n.codePanel,children:[e.jsxs("div",{className:n.row,children:[e.jsx(x,{weight:"semibold",children:X?"Monaco Editor":"Function Preview"}),A&&e.jsx(x,{size:200,style:{fontFamily:l.fontFamilyMonospace},children:A})]}),Y&&e.jsx(M,{intent:"error",children:e.jsx(D,{children:Y})}),ie?e.jsx(x,{style:{color:l.colorNeutralForeground3},children:"Loading source…"}):e.jsx("div",{style:{height:240},children:e.jsx(pe,{language:"javascript",value:te,readOnly:!X,onChange:r=>{$(r),J(!0)},options:{wordWrap:"on"}})}),e.jsxs("div",{className:n.row,children:[e.jsx(m,{appearance:"subtle",size:"small",onClick:()=>{Q(null),I(null),J(!1)},children:"Close"}),X&&e.jsx(m,{appearance:"primary",size:"small",onClick:()=>{Pe()},disabled:!Ce||ie||!!Y,children:"Save Web Resource"})]})]})]},a);if(s.kind==="url"){const r=s.address.trim().startsWith("https://");return e.jsxs("div",{className:n.actionCard,children:[e.jsxs("div",{className:n.actionHeader,children:[e.jsx(L,{appearance:"filled",color:"informative",size:"small",children:"URL"}),e.jsx(m,{appearance:"subtle",size:"small",icon:e.jsx(z,{}),onClick:()=>K(a),"aria-label":"Remove action"})]}),e.jsx(M,{intent:"warning",children:e.jsx(D,{children:e.jsx(x,{className:n.securityNote,children:"⚠ Ampersands in URLs are automatically escaped as & in the generated XML."})})}),e.jsx(v,{label:"Address",validationState:r?"none":"error",validationMessage:r?void 0:"URL must start with https://",children:e.jsx(S,{value:s.address,onChange:(o,c)=>g(a,{...s,address:c.value}),placeholder:"https://..."})}),e.jsx(v,{label:"Open in (WinMode)",children:e.jsxs(V,{value:String(s.winMode??0),onChange:(o,c)=>g(a,{...s,winMode:parseInt(c.value)}),children:[e.jsx("option",{value:"0",children:"Navigate (0)"}),e.jsx("option",{value:"1",children:"Dialog (1)"}),e.jsx("option",{value:"2",children:"Popup (2)"})]})}),e.jsx(v,{children:e.jsxs(m,{appearance:s.passParams?"primary":"subtle",size:"small",onClick:()=>g(a,{...s,passParams:!s.passParams}),children:[s.passParams?"✓ PassParams ON":"PassParams OFF"," — appends typename, type, id, orgname…"]})}),e.jsx(ee,{children:"Parameters (named)"}),e.jsx(he,{params:s.params,onChange:o=>g(a,{...s,params:o}),urlMode:!0})]},a)}return s.kind==="powerFx"?e.jsxs("div",{className:n.actionCard,children:[e.jsxs("div",{className:n.actionHeader,children:[e.jsx(L,{appearance:"filled",color:"brand",size:"small",children:"Power Fx"}),e.jsx(m,{appearance:"subtle",size:"small",icon:e.jsx(z,{}),onClick:()=>K(a),"aria-label":"Remove action"})]}),e.jsx(v,{label:"Expression",children:e.jsx("div",{style:{height:120,border:`1px solid ${l.colorNeutralStroke1}`,borderRadius:l.borderRadiusMedium,overflow:"hidden"},children:e.jsx(pe,{language:"javascript",value:s.expression,onChange:r=>g(a,{...s,expression:r??""}),options:{minimap:{enabled:!1},lineNumbers:"off",fontSize:13,scrollBeyondLastLine:!1,wordWrap:"on",lineDecorationsWidth:4,lineNumbersMinChars:0,glyphMargin:!1,folding:!1,renderLineHighlight:"none"}})})}),e.jsx(M,{intent:"info",children:e.jsxs(D,{children:["Variables: ",e.jsx("code",{children:"ThisRecord"}),", ",e.jsx("code",{children:"Selection"}),", ",e.jsx("code",{children:"Self"}),". Power Fx rules can return a Promise on Unified Interface (resolves false after 10 s if unresolved)."]})})]},a):s.kind==="customApi"?e.jsxs("div",{className:n.actionCard,children:[e.jsxs("div",{className:n.actionHeader,children:[e.jsx(L,{appearance:"filled",color:"warning",size:"small",children:"Custom API"}),e.jsx(m,{appearance:"subtle",size:"small",icon:e.jsx(z,{}),onClick:()=>K(a),"aria-label":"Remove action"})]}),e.jsx(v,{label:"Action logical name",children:e.jsx(S,{value:s.actionName,onChange:(r,o)=>g(a,{...s,actionName:o.value}),placeholder:"new_ExecuteBusinessAction"})}),e.jsx(v,{label:"Bound parameter (optional)",children:e.jsx(S,{value:s.boundParameter??"",onChange:(r,o)=>g(a,{...s,boundParameter:o.value}),placeholder:"Target"})}),e.jsx(v,{label:"Input parameters (name=value per line)",children:e.jsx(S,{value:s.inputParameters.map(r=>`${r.name}=${r.value}`).join("; "),onChange:(r,o)=>{const c=o.value.split(";").map(b=>b.trim()).filter(Boolean).map(b=>{const[_,...Be]=b.split("=");return{name:(_??"").trim(),value:Be.join("=").trim()}}).filter(b=>b.name.length>0);g(a,{...s,inputParameters:c})},placeholder:"ParamA=ValueA; ParamB=ValueB"})})]},a):null},ke=()=>e.jsxs(e.Fragment,{children:[t.actions.map((s,a)=>Ie(s,a)),t.actions.length===0&&e.jsx(x,{italic:!0,style:{color:l.colorNeutralForeground3},children:"No actions defined — button will do nothing when clicked."}),e.jsxs("div",{className:n.row,children:[e.jsx(v,{label:"Action type",style:{minWidth:"220px"},children:e.jsxs(V,{onChange:(s,a)=>{const u=a.value;u&&T(u)},value:"",children:[e.jsx("option",{value:"",children:"Add action..."}),e.jsx("option",{value:"javascript",children:"JavaScript function"}),e.jsx("option",{value:"url",children:"URL action"}),e.jsx("option",{value:"powerFx",children:"Power Fx expression"}),e.jsx("option",{value:"customApi",children:"Custom action / Web API"})]})}),e.jsx(m,{icon:e.jsx(U,{}),appearance:"secondary",size:"small",onClick:()=>T("javascript"),children:"Add JavaScript function"}),e.jsx(m,{icon:e.jsx(U,{}),appearance:"secondary",size:"small",onClick:()=>T("url"),children:"Add URL action"}),e.jsx(m,{icon:e.jsx(U,{}),appearance:"secondary",size:"small",onClick:()=>T("powerFx"),children:"Add Power Fx action"}),e.jsx(m,{icon:e.jsx(U,{}),appearance:"secondary",size:"small",onClick:()=>T("customApi"),children:"Add Custom API action"})]})]}),ze=()=>e.jsxs(e.Fragment,{children:[e.jsx(v,{label:"Command ID",children:e.jsx(S,{value:w,onChange:(s,a)=>se(a.value),style:{fontFamily:l.fontFamilyMonospace}})}),G&&e.jsx(x,{style:{color:l.colorPaletteRedForeground1,fontSize:l.fontSizeBase100},children:G}),e.jsx(m,{appearance:"secondary",size:"small",disabled:!w.trim()||!!G||w===t.id,onClick:()=>{if(!w.trim()||G)return;const s=w.trim();p(t.id,s)&&C(s)},children:"Apply ID change"}),e.jsx(x,{style:{color:l.colorNeutralForeground3,fontSize:l.fontSizeBase200},children:"Naming convention: Publisher.EntityName.ButtonName.Command"}),e.jsx(M,{intent:"warning",children:e.jsx(D,{children:e.jsxs(x,{className:n.securityNote,children:["⚠ ",e.jsx("strong",{children:"Security:"})," All command definitions are visible in browser source regardless of button visibility. Do not embed sensitive logic, credentials, or privileged information in command parameters or function names."]})})})]}),ue=s=>{const a=s==="enable"?t.enableRules:t.displayRules,u=(s==="enable"?f:d).map(c=>c.id).filter(c=>!a.includes(c)),r=s==="enable"?ge:ye,o=()=>{const c=new Set([...f.map(_=>_.id),...d.map(_=>_.id)]),b=Le("New",s==="enable"?"Enable":"Display",c);s==="enable"?je({id:b,steps:[]}):ve({id:b,steps:[]}),H(b,s)};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:n.rulePills,children:[a.map(c=>e.jsxs("div",{className:n.ruleRow,children:[e.jsx(L,{appearance:"outline",size:"medium",className:n.ruleChip,onClick:()=>H(c,s),role:"button",tabIndex:0,children:c}),e.jsx(m,{appearance:"subtle",size:"small",className:n.ruleRemoveBtn,icon:e.jsx(z,{}),"aria-label":`Unbind ${c}`,onClick:()=>{k(s==="enable"?{enableRules:t.enableRules.filter(b=>b!==c)}:{displayRules:t.displayRules.filter(b=>b!==c)})}})]},c)),a.length===0&&e.jsxs(x,{italic:!0,style:{color:l.colorNeutralForeground3},children:["No ",s," rules — always ",s==="enable"?"enabled":"visible","."]})]}),e.jsxs("div",{className:n.row,children:[e.jsx(v,{label:`Bind existing ${s} rule`,style:{minWidth:"260px"},children:e.jsxs(V,{value:r,onChange:(c,b)=>s==="enable"?ae(b.value):le(b.value),children:[e.jsx("option",{value:"",children:"Select a rule…"}),u.map(c=>e.jsx("option",{value:c,children:c},c))]})}),e.jsx(m,{appearance:"secondary",size:"small",disabled:!r,onClick:()=>{r&&(s==="enable"?(k({enableRules:[...t.enableRules,r]}),ae("")):(k({displayRules:[...t.displayRules,r]}),le("")))},children:"Bind selected"}),e.jsxs(m,{appearance:"subtle",size:"small",onClick:o,children:["Create new ",s," rule"]})]}),s==="enable"&&e.jsx(M,{intent:"info",children:e.jsxs(D,{children:["Disabled buttons are ",e.jsx("strong",{children:"hidden"})," in the modern command bar (Unified Interface). In the classic ribbon, disabled buttons remain visible but do not respond to clicks."]})})]})},Fe=()=>e.jsxs(e.Fragment,{children:[e.jsxs(x,{children:["Referenced by ",e.jsx("strong",{children:ce})," button(s)."]}),Z.length>0&&e.jsx("div",{className:n.versionsList,children:Z.map(s=>e.jsx("div",{className:n.versionRow,children:e.jsxs("div",{children:[e.jsx(x,{weight:"semibold",style:{fontFamily:l.fontFamilyMonospace},children:s.button.id}),e.jsxs(x,{className:n.versionMeta,children:[s.location," → ",s.tab.label," → ",s.group.label]})]})},`${s.location}:${s.tab.id}:${s.group.id}:${s.button.id}`))})]}),me=be.filter(s=>s.target===t.id||s.detail.includes(t.id)).slice().reverse(),Ae=()=>e.jsx(e.Fragment,{children:me.length===0?e.jsx(x,{style:{color:l.colorNeutralForeground3},children:"No command-specific history entries yet."}):e.jsx("div",{className:n.versionsList,children:me.map((s,a)=>e.jsxs("div",{className:n.versionRow,children:[e.jsxs("div",{children:[e.jsx(x,{weight:"semibold",children:s.op}),e.jsx(x,{className:n.versionMeta,children:s.detail})]}),e.jsx(x,{className:n.versionMeta,children:new Date(s.ts).toLocaleString()})]},`${s.ts}-${a}`))})});return e.jsxs($e,{position:"end",open:F,onOpenChange:()=>y(),className:n.drawer,children:[e.jsx(Te,{children:e.jsx(_e,{action:e.jsx(m,{appearance:"subtle",icon:e.jsx(z,{}),onClick:y,"aria-label":"Close command editor"}),children:e.jsx(x,{size:400,weight:"semibold",style:{fontFamily:l.fontFamilyMonospace},children:t.id})})}),e.jsxs(Ue,{className:n.body,children:[e.jsxs(Ve,{selectedValue:P,onTabSelect:(s,a)=>fe(a.value),children:[e.jsx(E,{value:"actions",children:"Actions"}),e.jsx(E,{value:"enableRules",children:"Enable rules"}),e.jsx(E,{value:"displayRules",children:"Display rules"}),e.jsx(E,{value:"settings",children:"Settings"}),e.jsxs(E,{value:"references",children:["References (",ce,")"]}),e.jsx(E,{value:"versions",children:"Versions"})]}),e.jsx(ee,{}),P==="actions"&&ke(),P==="enableRules"&&ue("enable"),P==="displayRules"&&ue("display"),P==="settings"&&ze(),P==="references"&&Fe(),P==="versions"&&Ae()]})]})};export{ls as CommandEditorPanel,ls as default};
@@ -1 +0,0 @@
1
- import{cw as a,bL as te,cx as oe}from"./fluent-icons-DiKr_qRE.js";import{r as u}from"./monaco-BLZnQb2P.js";import{i,u as c,h as E,e as b}from"./index-DjHxPFpB.js";import{a1 as t,B as ae,Q as S}from"./fluent-ui-kUA2U4Gr.js";import"./dnd-DHB99ZH7.js";const ne=oe({backdrop:{position:"fixed",inset:0,backgroundColor:"rgba(0,0,0,0.5)",zIndex:1e3,display:"flex",alignItems:"flex-start",justifyContent:"center",paddingTop:"10vh"},palette:{width:"640px",maxWidth:"90vw",backgroundColor:t.colorNeutralBackground1,borderRadius:t.borderRadiusLarge,boxShadow:t.shadow64,overflow:"hidden"},searchRow:{display:"flex",alignItems:"center",padding:`${t.spacingVerticalM} ${t.spacingHorizontalM}`,borderBottom:`1px solid ${t.colorNeutralStroke1}`,gap:t.spacingHorizontalS},searchInput:{flex:1,border:"none",outline:"none",fontSize:t.fontSizeBase400,backgroundColor:"transparent"},results:{maxHeight:"400px",overflowY:"auto"},group:{paddingTop:t.spacingVerticalXS},groupLabel:{padding:`${t.spacingVerticalXXS} ${t.spacingHorizontalM}`,color:t.colorNeutralForeground3,fontSize:t.fontSizeBase100,fontWeight:t.fontWeightSemibold,textTransform:"uppercase",letterSpacing:"0.08em"},item:{display:"flex",alignItems:"center",gap:t.spacingHorizontalS,padding:`${t.spacingVerticalXS} ${t.spacingHorizontalM}`,cursor:"pointer","&:hover":{backgroundColor:t.colorNeutralBackground1Hover}},itemSelected:{backgroundColor:t.colorNeutralBackground1Hover},itemLabel:{flex:1},itemSub:{color:t.colorNeutralForeground3,fontSize:t.fontSizeBase200},footer:{padding:`${t.spacingVerticalXS} ${t.spacingHorizontalM}`,borderTop:`1px solid ${t.colorNeutralStroke1}`,color:t.colorNeutralForeground3,fontSize:t.fontSizeBase100,display:"flex",gap:t.spacingHorizontalL}}),de=()=>{const l=ne(),m=i(e=>e.commandPaletteOpen),w=i(e=>e.setCommandPaletteOpen),R=i(e=>e.openBulkPublish),B=i(e=>e.openXmlDrawer),M=i(e=>e.openImportXml),L=i(e=>e.openCommandEditor),N=i(e=>e.openRuleEditor),X=i(e=>e.openNewGroup),D=i(e=>e.openNewButton),T=i(e=>e.openLocalizationEditor),v=i(e=>e.themeMode),H=i(e=>e.setThemeMode),P=c(e=>e.undo),W=c(e=>e.redo),O=c(e=>e.commands),G=c(e=>e.displayRules),V=c(e=>e.enableRules),y=c(e=>e.ribbons),F=E(e=>e.entities),A=E(e=>e.setActiveEntity),U=b(e=>e.location),Q=b(e=>e.tabId),h=b(e=>e.selectedButtonId),K=b(e=>e.selectedGroupId),[s,C]=u.useState(""),[g,d]=u.useState(0),$=u.useRef(null),n=u.useCallback(()=>{w(!1),C(""),d(0)},[w]);u.useEffect(()=>{m&&setTimeout(()=>$.current?.focus(),50)},[m]);const Z=()=>{const e=[],Y=y[U].tabs.find(o=>o.id===Q)?.groups[0]?.id??null,x=K??Y,J=[{id:"publish",label:"Publish all",subtitle:"Save and publish changes to Dataverse",kind:"action",action:()=>{R(),n()}},{id:"view-xml",label:"View RibbonDiffXml",subtitle:"Open XML drawer",kind:"action",action:()=>{B(),n()}},{id:"import-xml",label:"Import XML",subtitle:"Import RibbonDiffXml from clipboard",kind:"action",action:()=>{M(),n()}},{id:"new-group",label:"New group",subtitle:"Create a new ribbon group in current tab",kind:"action",action:()=>{X(),n()}},{id:"new-button",label:"New button",subtitle:x?"Create a new button in selected/current group":"Select a tab/group with at least one group first",kind:"action",action:()=>{x&&(D(x),n())}},{id:"edit-labels",label:"Edit localized labels",subtitle:h?"Open localization editor for selected button":"Select a button first",kind:"action",action:()=>{h&&(T(h),n())}},{id:"toggle-theme",label:`Toggle theme (${v==="dark"?"Dark":"Light"})`,subtitle:"Switch between light and dark",kind:"action",action:()=>{H(v==="dark"?"light":"dark"),n()}},{id:"undo",label:"Undo",subtitle:"Ctrl+Z",kind:"action",action:()=>{P(),n()}},{id:"redo",label:"Redo",subtitle:"Ctrl+Shift+Z",kind:"action",action:()=>{W(),n()}}];if(e.push(...J),!s.startsWith("@")&&!s.startsWith("/")){const o=Object.entries(y).flatMap(([_,ee])=>ee.tabs.flatMap(j=>j.groups.flatMap(z=>z.buttons.map(k=>({id:`btn-${k.id}`,label:k.label||k.id,subtitle:`${_} → ${j.label} → ${z.label}`,kind:"button",action:()=>{n()}})))));e.push(...o.slice(0,20))}return O.forEach(o=>{e.push({id:`cmd-${o.id}`,label:o.id,subtitle:`${o.actions.length} action(s)`,kind:"command",action:()=>{L(o.id),n()}})}),G.forEach(o=>{e.push({id:`dr-${o.id}`,label:o.id,subtitle:`Display rule — ${o.steps.length} step(s)`,kind:"rule",action:()=>{N(o.id,"display"),n()}})}),V.forEach(o=>{e.push({id:`er-${o.id}`,label:o.id,subtitle:`Enable rule — ${o.steps.length} step(s)`,kind:"rule",action:()=>{N(o.id,"enable"),n()}})}),(s.startsWith("@")||!s)&&F.slice(0,30).forEach(o=>{e.push({id:`ent-${o.logicalName}`,label:o.displayName,subtitle:o.logicalName,kind:"entity",action:()=>{A(o),n()}})}),e},f=s.startsWith("@")||s.startsWith("/")?s.slice(1):s,I=Z(),p=f?I.filter(e=>e.label.toLowerCase().includes(f.toLowerCase())||(e.subtitle??"").toLowerCase().includes(f.toLowerCase())):I,q=e=>{e.key==="ArrowDown"?(e.preventDefault(),d(r=>Math.min(r+1,p.length-1))):e.key==="ArrowUp"?(e.preventDefault(),d(r=>Math.max(r-1,0))):e.key==="Enter"?p[g]?.action():e.key==="Escape"&&n()};return m?a.jsx("div",{className:l.backdrop,onClick:n,role:"presentation",children:a.jsxs("div",{className:l.palette,onClick:e=>e.stopPropagation(),role:"dialog","aria-modal":"true","aria-label":"Command palette",children:[a.jsxs("div",{className:l.searchRow,children:[a.jsx(te,{style:{color:t.colorNeutralForeground3,flexShrink:0}}),a.jsx("input",{ref:$,className:l.searchInput,value:s,onChange:e=>{C(e.target.value),d(0)},onKeyDown:q,placeholder:"Search commands, buttons, entities… Use @ for entities, / for actions","aria-label":"Command palette search"})]}),a.jsxs("div",{className:l.results,role:"listbox",children:[p.map((e,r)=>a.jsxs("div",{className:`${l.item} ${r===g?l.itemSelected:""}`,onClick:e.action,role:"option","aria-selected":r===g,onMouseEnter:()=>d(r),children:[a.jsx(ae,{appearance:"outline",size:"small",children:e.kind}),a.jsxs("div",{className:l.itemLabel,children:[a.jsx(S,{children:e.label}),e.subtitle&&a.jsx(S,{className:l.itemSub,block:!0,children:e.subtitle})]})]},e.id)),p.length===0&&a.jsx("div",{className:l.item,children:a.jsx(S,{style:{color:t.colorNeutralForeground3},children:"No results"})})]}),a.jsxs("div",{className:l.footer,children:[a.jsx("span",{children:"↑↓ navigate"}),a.jsx("span",{children:"↵ select"}),a.jsx("span",{children:"Esc close"}),a.jsx("span",{children:"@ entities"}),a.jsx("span",{children:"/ actions"})]})]})}):null};export{de as CommandPalette,de as default};
@@ -1 +0,0 @@
1
- import{cw as e,aw as k,b9 as C,bl as D,cx as B}from"./fluent-icons-DiKr_qRE.js";import{r as d}from"./monaco-BLZnQb2P.js";import{i as u,u as I}from"./index-DjHxPFpB.js";import{x as M,l as R,m as H,H as L,a as N,k as E,Q as a,a1 as o,u as x,w as h,G as F,B as z,V as O}from"./fluent-ui-kUA2U4Gr.js";import"./dnd-DHB99ZH7.js";function $(){return window.dataverseAPI}function P(i){const l=i.map(s=>{const r=s.publisherid,c=s.versionnumber,m=typeof c=="number"?c:Number(c??0)||0;return{solutionId:String(s.solutionid??""),solutionName:String(s.friendlyname??s.uniquename??"Unknown Solution"),publisher:String(r?.friendlyname??r?.customizationprefix??"Unknown Publisher"),managed:!!s.ismanaged,importedOn:s.modifiedon?String(s.modifiedon):void 0,wins:!1,versionNumber:m}});return l.sort((s,r)=>s.versionNumber-r.versionNumber),l.length>0&&(l[l.length-1].wins=!0),l.map(({versionNumber:s,...r})=>r)}async function A(i){if(!i)return null;const r=(await $().getSolutions(["solutionid","friendlyname","uniquename","ismanaged","publisherid","versionnumber","modifiedon"])).value;return r.length<=1?null:{elementId:i,elementKind:"button",solutions:P(r)}}const W=B({drawer:{width:"560px",maxWidth:"95vw"},body:{display:"flex",flexDirection:"column",gap:o.spacingHorizontalM,padding:o.spacingHorizontalM,overflowY:"auto"},solutionRow:{display:"flex",flexDirection:"column",gap:o.spacingHorizontalXS,padding:o.spacingHorizontalS,border:`1px solid ${o.colorNeutralStroke2}`,borderRadius:o.borderRadiusMedium,backgroundColor:o.colorNeutralBackground2},solutionRowWinner:{border:`2px solid ${o.colorBrandStroke1}`,backgroundColor:o.colorBrandBackground2},solutionHeader:{display:"flex",alignItems:"center",gap:o.spacingHorizontalS},elementId:{fontFamily:o.fontFamilyMonospace,fontSize:o.fontSizeBase200,backgroundColor:o.colorNeutralBackground4,padding:`2px ${o.spacingHorizontalXS}`,borderRadius:o.borderRadiusSmall,wordBreak:"break-all"}}),_=()=>{const i=W(),l=u(n=>n.conflictDrawerOpen),s=u(n=>n.conflictElementId),r=u(n=>n.closeConflictDrawer),c=u(n=>n.openXmlDrawer),m=I(n=>n.conflicts),[p,b]=d.useState(null),[j,f]=d.useState(!1),[w,g]=d.useState(null);d.useEffect(()=>{if(!l||!s){b(null),g(null),f(!1);return}let n=!1;return f(!0),g(null),A(s).then(t=>{n||b(t)}).catch(t=>{n||g(t instanceof Error?t.message:"Failed to load conflict layers")}).finally(()=>{n||f(!1)}),()=>{n=!0}},[l,s]);const v=m.filter(n=>n.elementId===s),y=d.useMemo(()=>p||v[0],[p,v]),S=y?[...y.solutions].sort((n,t)=>n.wins===t.wins?0:n.wins?1:-1):[];return e.jsxs(M,{className:i.drawer,open:l,position:"end",onOpenChange:(n,t)=>!t.open&&r(),children:[e.jsx(R,{children:e.jsx(H,{action:e.jsx(N,{appearance:"subtle",icon:e.jsx(k,{}),onClick:r,"aria-label":"Close"}),children:e.jsx(L,{children:"Solution Conflicts"})})}),e.jsx(E,{children:e.jsxs("div",{className:i.body,children:[s&&e.jsxs("div",{children:[e.jsx(a,{size:200,style:{color:o.colorNeutralForeground3},children:"Conflicting element:"}),e.jsx("div",{className:i.elementId,children:s})]}),e.jsx(x,{intent:"warning",children:e.jsx(h,{children:e.jsx(a,{size:200,children:"Multiple solutions customize this element. Dataverse applies them in solution import order — the most recently imported solution wins."})})}),e.jsx(x,{intent:"info",children:e.jsx(h,{children:e.jsxs(a,{size:200,children:[e.jsx("strong",{children:"To resolve:"})," Merge changes into one solution, or use solution layering to control evaluation order. Managed solutions appear as read-only layers — to resolve, merge the customization into your unmanaged solution."]})})}),j&&e.jsx("div",{style:{display:"flex",justifyContent:"center",padding:o.spacingHorizontalM},children:e.jsx(F,{label:"Loading solution layers..."})}),w&&e.jsx(x,{intent:"error",children:e.jsx(h,{children:w})}),!j&&S.length===0&&e.jsx(a,{style:{color:o.colorNeutralForeground3,textAlign:"center"},children:"No conflict details available from environment layers."}),S.map((n,t)=>e.jsxs("div",{className:`${i.solutionRow} ${n.wins?i.solutionRowWinner:""}`,children:[e.jsxs("div",{className:i.solutionHeader,children:[e.jsx(a,{weight:"semibold",children:n.solutionName}),n.wins&&e.jsx(z,{appearance:"filled",color:"brand",children:"WINS"}),n.managed&&e.jsx(O,{content:"Managed solution — read-only",relationship:"label",children:e.jsx(C,{style:{color:o.colorNeutralForeground3}})}),e.jsx(z,{appearance:"outline",size:"small",children:n.managed?"Managed":"Unmanaged"})]}),e.jsxs(a,{size:200,style:{color:o.colorNeutralForeground3},children:["Publisher: ",n.publisher]}),n.importedOn&&e.jsxs(a,{size:200,style:{color:o.colorNeutralForeground3},children:["Imported: ",new Date(n.importedOn).toLocaleString()]}),e.jsx("div",{style:{display:"flex",gap:o.spacingHorizontalS,flexWrap:"wrap"},children:e.jsx(N,{appearance:"subtle",size:"small",icon:e.jsx(D,{}),onClick:c,children:"View XML diff"})})]},`${n.solutionId}-${t}`))]})})]})};export{_ as ConflictDrawer,_ as default};
@@ -1,7 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/monaco-BLZnQb2P.js","assets/monaco-Dvl_Svmm.css"])))=>i.map(i=>d[i]);
2
- import{b as g,r as b,_ as M}from"./monaco-BLZnQb2P.js";import{cw as s,aw as E,cx as C}from"./fluent-icons-DiKr_qRE.js";import{i as x,u as m}from"./index-DjHxPFpB.js";import{g as N}from"./xmlGenerator-DEaVrfZJ.js";import{x as O,l as _,m as V,H as $,a as S,k as X,u as I,w as G,Q as T,B as D,G as A,a1 as r}from"./fluent-ui-kUA2U4Gr.js";import"./dnd-DHB99ZH7.js";const P=g.lazy(()=>M(()=>import("./monaco-BLZnQb2P.js").then(n=>n.i),__vite__mapDeps([0,1])).then(n=>({default:n.DiffEditor}))),W=["HomepageGrid","SubGrid","Form","Application"],U=C({drawer:{},body:{display:"flex",flexDirection:"column",flex:"1 1 auto",minHeight:0,overflow:"hidden",gap:r.spacingHorizontalS},statsBar:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,padding:`${r.spacingVerticalXS} ${r.spacingHorizontalM}`,flexShrink:0},toggleRow:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,padding:`${r.spacingVerticalXS} ${r.spacingHorizontalM}`,borderBottom:`1px solid ${r.colorNeutralStroke2}`,flexShrink:0},editorWrap:{flex:1,height:0,minHeight:"400px",overflow:"hidden",position:"relative"}});function F(n,o){const l=n.split(`
3
- `),c=o.split(`
4
- `);let d=0,t=0;const f=new Set(l),a=new Set(c);for(const i of c)f.has(i)||d++;for(const i of l)a.has(i)||t++;return{added:d,removed:t}}function B(n,o,l,c,d,t,f){const a=[];for(const i of W){const p=f?o[i]:n[i],u=o[i];try{a.push(`<!-- ${i} -->
5
- `+N({location:i,current:p,baseline:u,commands:l,displayRules:c,enableRules:d,locLabels:t,entityLogicalName:p.entityLogicalName}))}catch(h){a.push(`<!-- ${i}: Error generating XML: ${String(h)} -->`)}}return a.join(`
6
-
7
- `)}const ee=()=>{const n=U(),o=x(e=>e.diffViewerOpen),l=x(e=>e.diffViewerMode),c=x(e=>e.closeDiffViewer),d=x(e=>e.themeMode),[t,f]=g.useState(!0),a=m(e=>e.ribbons),i=m(e=>e.baseline),p=m(e=>e.commands),u=m(e=>e.displayRules),h=m(e=>e.enableRules),y=m(e=>e.locLabels),k=d==="dark",j=b.useMemo(()=>B(a,i,p,u,h,y,!0),[o]),w=b.useMemo(()=>B(a,i,p,u,h,y,!1),[o,a,i,p,u,h,y]),{added:L,removed:R}=F(j,w),v=g.useRef(null),z=g.useCallback(e=>{v.current=e,e.updateOptions({renderSideBySide:t})},[]);return g.useEffect(()=>{v.current?.updateOptions({renderSideBySide:t})},[t]),s.jsxs(O,{className:n.drawer,open:o,position:"end",size:"full",onOpenChange:(e,H)=>!H.open&&c(),children:[s.jsx(_,{children:s.jsx(V,{action:s.jsx(S,{appearance:"subtle",icon:s.jsx(E,{}),onClick:c,"aria-label":"Close"}),children:s.jsx($,{children:l==="compare"?"Compare to baseline":"Diff viewer"})})}),s.jsx(X,{style:{display:"flex",flexDirection:"column",flex:"1 1 auto",minHeight:0,overflow:"hidden"},children:s.jsxs("div",{className:n.body,children:[s.jsx(I,{intent:"info",children:s.jsx(G,{children:s.jsx(T,{size:200,children:l==="compare"?"Showing current state vs. last published baseline.":"Showing the change introduced by this history entry."})})}),s.jsxs("div",{className:n.toggleRow,children:[s.jsxs(D,{appearance:"tint",color:"success",children:["+",L," lines"]}),s.jsxs(D,{appearance:"tint",color:"danger",children:["-",R," lines"]}),s.jsx("div",{style:{flex:1}}),s.jsx(S,{appearance:t?"primary":"subtle",size:"small",onClick:()=>f(!0),children:"Side by side"}),s.jsx(S,{appearance:t?"subtle":"primary",size:"small",onClick:()=>f(!1),children:"Unified"})]}),s.jsx("div",{className:n.editorWrap,children:s.jsx(b.Suspense,{fallback:s.jsx("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%"},children:s.jsx(A,{size:"medium",label:"Loading diff editor…"})}),children:s.jsx(P,{original:j,modified:w,language:"xml",theme:k?"vs-dark":"vs",height:"100%",onMount:z,options:{readOnly:!0,renderSideBySide:t,lineNumbers:"on",minimap:{enabled:!1},scrollBeyondLastLine:!1,automaticLayout:!0,wordWrap:"on"}})})})]})})]})};export{ee as DiffViewer,ee as default};
@@ -1 +0,0 @@
1
- import{cw as o,aw as re,bL as E,ad as ae,cx as se}from"./fluent-icons-DiKr_qRE.js";import{r as t,b as te}from"./monaco-BLZnQb2P.js";import{i as M,u as ne,e as C,h as ie,F as le,d as ce,f as de}from"./index-DjHxPFpB.js";import{b as U,s as G,p as ue}from"./webResourceService-Ck07E3GN.js";import{d as ge,h as pe,f as he,i as me,H as be,a as k,g as ye,K as fe,T as L,I as F,b as we,O as xe,J as Se,a1 as r,Q as y,B as Ce,e as ke}from"./fluent-ui-kUA2U4Gr.js";import"./dnd-DHB99ZH7.js";function _(s){return s.replace(/([A-Z])/g,(n,i,c)=>(c>0?"_":"")+n.toLowerCase())}function ve(s){const n=new TextEncoder().encode(s);let i="";for(let c=0;c<n.length;c++)i+=String.fromCharCode(n[c]);return btoa(i)}const je=[{category:"Actions",keywords:["Add","Delete","Edit","Save","Copy","Paste","Undo","Redo","Send","Print","Refresh"]},{category:"Communication",keywords:["Mail","Chat","Phone","Call","Message"]},{category:"Navigation",keywords:["Arrow","Chevron","Navigation","Home","Back","Forward"]},{category:"System",keywords:["Settings","Info","Warning","Dismiss","Question","Checkmark","Error"]},{category:"Security",keywords:["Lock","Shield","Key","Fingerprint"]},{category:"People",keywords:["Person","People","Contact","User"]},{category:"Business",keywords:["Building","Briefcase","Money","Credit","Cart","Tag","Receipt"]},{category:"Files",keywords:["Document","Folder","Attach","Upload","Download","File"]},{category:"Web",keywords:["Globe","Link","Open","Browser","World"]},{category:"Time",keywords:["Calendar","Clock","Timer","History"]},{category:"Rating",keywords:["Star","Heart","Thumb"]},{category:"View",keywords:["Eye","Zoom","View","Window","Preview"]},{category:"Layout",keywords:["Grid","List","Table","Panel","Column","Row"]},{category:"Development",keywords:["Code","Bug","Branch","Wrench","Tool","Terminal"]},{category:"Media",keywords:["Play","Pause","Stop","Video","Audio","Camera"]},{category:"Analytics",keywords:["Chart","Data","Poll","Graph","Trend"]}],Re=["Add","Delete","Edit","Save","Copy","Cut","ClipboardPaste","Share","Mail","Chat","Phone","Search","Filter","ArrowLeft","ArrowRight","ArrowUp","ArrowDown","ChevronDown","ChevronUp","Navigation","Home","Settings","Info","Warning","Checkmark","Dismiss","QuestionCircle","LockClosed","LockOpen","Shield","Person","People","PersonAdd","Building","Briefcase","Money","CreditCard","Cart","Tag","Document","DocumentBulletList","Folder","FolderOpen","Attach","ArrowDownload","ArrowUpload","Globe","Link","Open","Calendar","Clock","Timer","Star","Heart","ThumbLike","ThumbDislike","Eye","EyeOff","ZoomIn","ZoomOut","Maximize","Minimize","Grid","List","Table","TableSimple","Code","Bug","Play","Pause","Stop","Refresh","ArrowSync","ArrowUndo","ArrowRedo","Printer","Send","Rocket","Sparkle","Trophy","Lightbulb","Bot","DataBar","ChartMultiple","Poll"];function Be(s){for(const n of je)if(n.keywords.some(i=>s.includes(i)))return n.category;return"General"}const O=Re.map(s=>({name:s,category:Be(s)})),Ae=["All",...Array.from(new Set(O.map(s=>s.category))).sort()],Ie=se({surface:{width:"720px",maxWidth:"95vw",height:"min(580px, 90vh)",maxHeight:"90vh",overflow:"hidden"},dialogBody:{display:"flex",flexDirection:"column",height:"100%",minHeight:0},body:{display:"flex",flexDirection:"column",flex:1,minHeight:0,overflow:"hidden",gap:r.spacingHorizontalS},toolbar:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,flexWrap:"wrap",flexShrink:0},categoryPicker:{minWidth:"180px",maxWidth:"220px"},iconGrid:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(72px, 1fr))",gap:r.spacingHorizontalXS,overflowY:"auto",flex:1,minHeight:0,padding:r.spacingHorizontalXS},iconTile:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:"4px",padding:r.spacingHorizontalXS,borderRadius:r.borderRadiusMedium,border:"1px solid transparent",cursor:"pointer",minHeight:"64px",":hover":{backgroundColor:r.colorNeutralBackground3,border:`1px solid ${r.colorNeutralStroke1}`}},iconTileSelected:{backgroundColor:r.colorBrandBackground2,border:`1px solid ${r.colorBrandStroke1}`},iconLabel:{fontSize:r.fontSizeBase100,textAlign:"center",lineHeight:1.2,wordBreak:"break-word",color:r.colorNeutralForeground2},webResourceList:{flex:1,overflowY:"auto"},webResourceRow:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,padding:`${r.spacingHorizontalXS} ${r.spacingHorizontalS}`,cursor:"pointer",borderRadius:r.borderRadiusMedium,":hover":{backgroundColor:r.colorNeutralBackground3}},uploadArea:{flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:r.spacingHorizontalM,border:`2px dashed ${r.colorNeutralStroke2}`,borderRadius:r.borderRadiusMedium,color:r.colorNeutralForeground3}}),$e=()=>{const s=Ie(),n=M(e=>e.iconPickerOpen),i=M(e=>e.closeIconPicker),c=ne(e=>e.setButtonProp),f=C(e=>e.selectedButtonId),w=C(e=>e.selectedGroupId),v=C(e=>e.tabId),j=C(e=>e.location),D=ie(e=>e.publisherPrefix),[d,$]=t.useState("fluent"),[R,V]=t.useState(""),[x,X]=t.useState("All"),[B,Z]=t.useState("regular"),[l,Q]=t.useState(null),[b,A]=t.useState(""),[z,I]=t.useState([]),[H,W]=t.useState(!1),[T,Y]=t.useState(""),[P,S]=t.useState(!1);te.useEffect(()=>{!n||d!=="webresource"||(W(!0),U("svg").then(e=>I(e)).catch(()=>I([])).finally(()=>W(!1)))},[n,d]);const q=t.useMemo(()=>{const e=T.toLowerCase();return z.filter(a=>!e||a.name.toLowerCase().includes(e))},[T,z]),K=t.useMemo(()=>{const e=R.toLowerCase();return O.filter(a=>(x==="All"||a.category===x)&&(e===""||a.name.toLowerCase().includes(e)))},[R,x]),J=async()=>{if(!l||!f||!w)return;const e=D||"new",a=_(l),u=ce.getState();S(!0);try{const g=await de(l,32);if(!g)throw new Error(`Could not serialize Fluent icon "${l}"`);const p=`${e}_/icons/${a}.svg`,N=ve(g),{id:h}=await G(p,N,11,`${a}.svg`);try{await ue(h)}catch(m){u.logWarn("webresource",`Created icon web resource ${p} but publish failed: ${m instanceof Error?m.message:String(m)}. It will publish with the next Publish.`)}c(j,v,w,f,{icon:a,image16:`$webresource:${p}`,image32:`$webresource:${p}`}),u.logInfo("webresource",`Icon web resource ready: ${p}`)}catch(g){u.logWarn("webresource",`Fluent icon "${l}" could not be uploaded as a web resource (${g instanceof Error?g.message:String(g)}). Using preview-only; add a real icon via the Web resource tab.`),c(j,v,w,f,{icon:a,image16:void 0,image32:void 0})}finally{S(!1),i()}},ee=()=>{!b||!f||!w||(c(j,v,w,f,{image16:b,image32:b}),i())},oe=async e=>{S(!0);try{const a=await new Promise((p,N)=>{const h=new FileReader;h.onerror=()=>N(h.error??new Error("Failed to read SVG")),h.onload=()=>{const m=String(h.result??"");p(m.includes(",")?m.split(",")[1]??"":m)},h.readAsDataURL(e)}),u=`${D??"new"}_/icons/${e.name}`;await G(u,a,11,e.name),A(`$webresource:${u}`),$("webresource");const g=await U("svg");I(g)}finally{S(!1)}};return o.jsx(ge,{open:n,onOpenChange:(e,a)=>!a.open&&i(),children:o.jsx(pe,{className:s.surface,children:o.jsxs(he,{className:s.dialogBody,children:[o.jsx(me,{action:o.jsx(k,{appearance:"subtle",icon:o.jsx(re,{}),onClick:i,"aria-label":"Close"}),children:o.jsx(be,{children:"Choose Icon"})}),o.jsxs(ye,{className:s.body,children:[o.jsxs(fe,{selectedValue:d,onTabSelect:(e,a)=>$(a.value),size:"small",children:[o.jsx(L,{value:"fluent",children:"Fluent icons"}),o.jsx(L,{value:"webresource",children:"Web resources"}),o.jsx(L,{value:"upload",children:"Upload SVG"})]}),d==="fluent"&&o.jsxs(o.Fragment,{children:[o.jsxs("div",{className:s.toolbar,children:[o.jsx(F,{contentBefore:o.jsx(E,{}),placeholder:"Search icons…",value:R,onChange:(e,a)=>V(a.value),size:"small",style:{flex:1}}),o.jsx(we,{className:s.categoryPicker,placeholder:"Category",value:x,onOptionSelect:(e,a)=>X(String(a.optionValue??"All")),children:Ae.map(e=>o.jsx(xe,{value:e,text:e,children:e},e))}),o.jsx(Se,{label:B==="regular"?"Regular":"Filled",checked:B==="filled",onChange:(e,a)=>Z(a.checked?"filled":"regular")})]}),o.jsx("div",{className:s.iconGrid,children:K.map(e=>o.jsxs("div",{className:`${s.iconTile} ${l===e.name?s.iconTileSelected:""}`,onClick:()=>Q(e.name),role:"option","aria-selected":l===e.name,title:`${e.name} — ${e.category}`,children:[o.jsx(le,{name:_(e.name),size:24,variant:B}),o.jsx("span",{className:s.iconLabel,children:e.name})]},e.name))}),l&&o.jsxs("div",{style:{display:"flex",alignItems:"center",gap:r.spacingHorizontalS,padding:r.spacingHorizontalXS,backgroundColor:r.colorNeutralBackground3,borderRadius:r.borderRadiusMedium,flexShrink:0},children:[o.jsxs(y,{size:200,style:{fontFamily:r.fontFamilyMonospace},children:['ModernImage="',l,'"']}),o.jsx(Ce,{appearance:"tint",color:"success",children:"Selected"})]})]}),d==="webresource"&&o.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:r.spacingHorizontalS,flex:1},children:[o.jsx(F,{contentBefore:o.jsx(E,{}),placeholder:"Search SVG web resources...",value:T,onChange:(e,a)=>Y(a.value),size:"small"}),o.jsxs("div",{className:s.webResourceList,children:[H&&o.jsx(y,{size:200,style:{color:r.colorNeutralForeground3},children:"Loading web resources..."}),!H&&q.slice(0,200).map(e=>{const a=`$webresource:${e.name}`,u=b===a;return o.jsx("div",{className:s.webResourceRow,onClick:()=>A(a),style:{backgroundColor:u?r.colorBrandBackground2:void 0},children:o.jsx(y,{size:200,style:{fontFamily:r.fontFamilyMonospace},children:a})},e.id)})]}),o.jsx(F,{placeholder:"$webresource:publisher_/icons/…",value:b,onChange:(e,a)=>A(a.value)}),o.jsx(y,{size:100,style:{color:r.colorNeutralForeground3},children:"Both image16 and image32 will be set to this path. Use SVG for best results across all DPI levels."})]}),d==="upload"&&o.jsxs("div",{className:s.uploadArea,children:[o.jsx(ae,{fontSize:48,style:{opacity:.4}}),o.jsx(y,{children:"Drag an SVG file here, or click to browse"}),o.jsx(y,{size:200,style:{color:r.colorNeutralForeground3},children:"The file will be uploaded as a web resource in the active solution."}),o.jsx("input",{type:"file",accept:".svg",style:{display:"none"},id:"icon-upload-input",onChange:e=>{const a=e.target.files?.[0];a&&oe(a)}}),o.jsx("label",{htmlFor:"icon-upload-input",style:{display:"inline-block",cursor:"pointer",padding:"6px 12px",background:r.colorBrandBackground,color:r.colorNeutralForegroundOnBrand,borderRadius:r.borderRadiusMedium,fontSize:r.fontSizeBase300},children:P?"Uploading...":"Browse for SVG"})]})]}),o.jsxs(ke,{children:[o.jsx(k,{appearance:"secondary",onClick:i,children:"Cancel"}),d==="fluent"&&o.jsx(k,{appearance:"primary",disabled:!l||P,onClick:()=>{J()},children:P?"Adding icon…":`Use ${l??"icon"}`}),d==="webresource"&&o.jsx(k,{appearance:"primary",disabled:!b,onClick:ee,children:"Use web resource"})]})]})})})};export{$e as IconPickerModal,$e as default};
@@ -1,3 +0,0 @@
1
- import{cw as s}from"./fluent-icons-DiKr_qRE.js";import{r as g}from"./monaco-BLZnQb2P.js";import{i as A,u as j,e as C}from"./index-DjHxPFpB.js";import{M as $}from"./MonacoEditor-DFYisBG6.js";import{d as v,h as T,i as w,f as O,g as H,K as M,T as S,j as X,u as I,w as R,e as k,a as y}from"./fluent-ui-kUA2U4Gr.js";import"./dnd-DHB99ZH7.js";function h(i,p){const l=i.indexOf(p);return l<0?void 0:`Line ${i.slice(0,l).split(/\r?\n/).length}`}function B(i,p,l){const c=[],a=new DOMParser().parseFromString(i,"application/xml"),r=a.querySelector("parsererror");if(r){const n=r.textContent?.trim()??"Unknown",e=n.match(/line\s+(\d+)/i);return c.push({message:`XML parse error: ${n}`,lineHint:e?`Line ${e[1]}`:void 0}),c}const o=new Set([]);a.querySelectorAll("[Id]").forEach(n=>{const e=n.getAttribute("Id")??"";if(/\s/.test(e)){const t=h(i,`Id="${e}"`);c.push({message:`Element ID "${e}" contains invalid whitespace characters`,elementId:e,lineHint:t})}}),a.querySelectorAll("[LabelText]").forEach(n=>{const e=n.getAttribute("LabelText")??"",t=e.match(/^\$LocLabels:(.+)$/);if(t&&o.size>0&&!o.has(t[1])){const d=n.getAttribute("Id")??"",m=h(i,d?`Id="${d}"`:`LabelText="${e}"`);c.push({message:`Button label reference "$LocLabels:${t[1]}" has no matching LocLabel entry`,elementId:d||void 0,lineHint:m})}}),(i.includes("& ")||i.includes(`&
2
- `))&&c.push({message:'URL may contain an unescaped "&" — all ampersands in XML must be written as &amp;',lineHint:h(i,"& ")??h(i,`&
3
- `)}),a.querySelectorAll("Group").forEach(n=>{const e=[];n.querySelectorAll(":scope > Controls > Button, :scope > Controls > FlyoutAnchor, :scope > Controls > SplitButton").forEach(t=>{const d=parseInt(t.getAttribute("Sequence")??"0",10);if(e.includes(d)){const m=n.getAttribute("Id")??"?";c.push({message:`Two elements share Sequence "${d}" in group "${m}"`,elementId:m,lineHint:h(i,`Sequence="${d}"`)})}e.push(d)})});const u=new Set(["EntityPrivilegeRule","EntityPropertyRule","DeviceTypeRule","OptionSetRule","CrmOutlookClientVersionRule"]);return a.querySelectorAll("EnableRules > EnableRule").forEach(n=>{const e=n.getAttribute("Id")??"";u.forEach(t=>{n.querySelector(t)&&c.push({message:`Enable rule "${e}" contains "${t}" which is only valid in DisplayRules per the schema`,elementId:e,lineHint:h(i,`<${t}`)})})}),a.querySelectorAll("OrRule").forEach(n=>{const e=n.querySelectorAll(":scope > Or").length;e<2&&c.push({message:`OrRule requires at least 2 <Or> children (found ${e})`,lineHint:h(i,"<OrRule")})}),c}function P(i,p){const l=j.getState(),c=C.getState().location,a=new DOMParser().parseFromString(i,"application/xml");if(!a.querySelector("parsererror")&&(a.querySelectorAll("CommandDefinition").forEach(r=>{const o=r.getAttribute("Id");if(!o)return;const u=[],n=[];r.querySelectorAll("EnableRules > EnableRule").forEach(e=>{const t=e.getAttribute("Id");t&&u.push(t)}),r.querySelectorAll("DisplayRules > DisplayRule").forEach(e=>{const t=e.getAttribute("Id");t&&n.push(t)}),l.upsertCommand({id:o,enableRules:u,displayRules:n,actions:[]})}),a.querySelectorAll("LocLabel").forEach(r=>{const o=r.getAttribute("Id");if(!o)return;const u=[];r.querySelectorAll("Title").forEach(n=>{const e=Number(n.getAttribute("languagecode")??0),t=n.getAttribute("description")??"";e&&u.push({languageCode:e,description:t})}),l.upsertLocLabel({id:o,titles:u})}),a.querySelectorAll("EnableRules > EnableRule").forEach(r=>{const o=r.getAttribute("Id");o&&l.upsertEnableRule({id:o,steps:[]})}),a.querySelectorAll("DisplayRules > DisplayRule").forEach(r=>{const o=r.getAttribute("Id");o&&l.upsertDisplayRule({id:o,steps:[]})}),p==="replace")){const r=structuredClone(l.ribbons),o=r[c];a.querySelectorAll("CustomAction").forEach(u=>{const n=u.getAttribute("Location")??"",e=Number(u.getAttribute("Sequence")??0),t=u.querySelector("CommandUIDefinition > Button");if(!t)return;const d=t.getAttribute("Id")??"",m=t.getAttribute("LabelText")??d,E=t.getAttribute("Command")??"",q=t.getAttribute("TemplateAlias")??"o1";if(!d)return;let x=!1;for(const L of o.tabs){for(const f of L.groups)if(n.startsWith(f.id)){f.buttons.find(D=>D.id===d)||f.buttons.push({id:d,label:m,commandId:E,templateAlias:q,sequence:e,kind:"button",hidden:!1,oob:!1,custom:!0,managed:!1}),x=!0;break}if(x)break}}),l.loadRibbons(r)}}const Y=()=>{const i=A(e=>e.importXmlOpen),p=A(e=>e.closeImportXml),[l,c]=g.useState(""),[b,a]=g.useState([]),[r,o]=g.useState("replace"),u=()=>{const e=B(l);return a(e),e.length===0},n=()=>{u()&&(P(l,r),p())};return s.jsx(v,{open:i,onOpenChange:()=>p(),children:s.jsxs(T,{style:{maxWidth:"960px",width:"92vw",height:"80vh",maxHeight:"860px"},children:[s.jsx(w,{children:"Import RibbonDiffXml"}),s.jsxs(O,{style:{height:"100%",display:"flex",flexDirection:"column"},children:[s.jsxs(H,{style:{flex:1,minHeight:0,display:"flex",flexDirection:"column"},children:[s.jsxs(M,{selectedValue:r,onTabSelect:(e,t)=>o(t.value),children:[s.jsx(S,{value:"replace",children:"Replace current"}),s.jsx(S,{value:"append",children:"Merge / append"})]}),s.jsx(X,{style:{margin:"8px 0"}}),s.jsx("div",{style:{flex:1,minHeight:0},children:s.jsx($,{language:"xml",value:l,onChange:c,readOnly:!1,height:"100%",options:{wordWrap:"on",lineNumbers:"on",padding:{top:8}}})}),b.length>0&&s.jsx("div",{style:{marginTop:"8px",display:"flex",flexDirection:"column",gap:"4px"},children:b.map((e,t)=>s.jsx(I,{intent:"error",children:s.jsxs(R,{children:[e.message,e.lineHint?` (${e.lineHint})`:""]})},t))}),b.length===0&&l&&s.jsx(I,{intent:"success",children:s.jsx(R,{children:"XML is valid."})})]}),s.jsxs(k,{children:[s.jsx(y,{appearance:"secondary",onClick:p,children:"Cancel"}),s.jsx(y,{appearance:"secondary",onClick:u,disabled:!l.trim(),children:"Validate"}),s.jsx(y,{appearance:"primary",onClick:n,disabled:!l.trim(),children:"Import"})]})]})]})})};export{Y as ImportXmlModal,Y as default};