@mohsinonxrm/pptb-commandbar-studio 0.9.0-beta.1 → 0.9.0-beta.2

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 (151) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +11 -13
  3. package/dist/assets/BulkPublishModal-DjdSDcWe.js +36 -0
  4. package/dist/assets/CommandEditorPanel-DYsxUTOk.js +1 -0
  5. package/dist/assets/CommandPalette-DihgRpHI.js +1 -0
  6. package/dist/assets/CompareView-CdQo0D6e.js +7 -0
  7. package/dist/assets/CrmParameterEditor-DO6Rt764.js +1 -0
  8. package/dist/assets/EditorDrawer-Cid60F3b.js +2 -0
  9. package/dist/assets/HideInsteadOfDeleteModal-Bk_foggy.js +1 -0
  10. package/dist/assets/IconPickerModal-CW_pvpVS.js +1 -0
  11. package/dist/assets/ImportXmlModal-BcszuTi-.js +1 -0
  12. package/dist/assets/MonacoEditor-DweI16yt.js +2 -0
  13. package/dist/assets/NewButtonModal-C2fAUuZI.js +1 -0
  14. package/dist/assets/NewGroupModal-BDr4DPBs.js +1 -0
  15. package/dist/assets/NewTabModal-CYc1fc2A.js +1 -0
  16. package/dist/assets/RuleEditorPanel-BxGrJYo4.js +1 -0
  17. package/dist/assets/ScriptView-tkdIK4sg.js +1 -0
  18. package/dist/assets/TabDisplayRulesPanel-S_AxUWfB.js +1 -0
  19. package/dist/assets/TranslationsView-DZIGE2pC.js +1 -0
  20. package/dist/assets/WebResourceBrowser-Dc3kBMvH.js +1 -0
  21. package/dist/assets/XmlView-B0weY9hR.js +2 -0
  22. package/dist/assets/{dnd-C1w9VFfC.js → dnd-iy5K5XAJ.js} +2 -2
  23. package/dist/assets/fluent-ui-CQyNN9H3.js +59 -0
  24. package/dist/assets/index-DRTwBo4g.js +136 -0
  25. package/dist/assets/monaco-DQA8g3bM.css +1 -0
  26. package/dist/assets/monaco-cQE5XS3B.js +1010 -0
  27. package/dist/assets/monacoSetup-BIq1zGyP.js +1 -0
  28. package/dist/assets/preload-helper-PPVm8Dsz.js +1 -0
  29. package/dist/assets/{server.browser-xEJRzS2D.js → server.browser-DTeSoizu.js} +1 -1
  30. package/dist/assets/useReplaceWebResourceConfirm-BhU1AM5L.js +1 -0
  31. package/dist/assets/useStableKeys-49o4VnxU.js +1 -0
  32. package/dist/assets/{xmlValidator-PbODaIQV.js → xmlValidator-CnbyWxHe.js} +2 -2
  33. package/dist/icons/icon.svg +9 -5
  34. package/dist/index.html +4 -6
  35. package/package.json +3 -1
  36. package/dist/assets/BulkPublishModal-DzDZJg0U.js +0 -36
  37. package/dist/assets/CommandEditorPanel-DsCP9yG4.js +0 -1
  38. package/dist/assets/CommandPalette-ID3kRJ9l.js +0 -1
  39. package/dist/assets/CompareView-DGsrcdoN.js +0 -7
  40. package/dist/assets/CrmParameterEditor-C22QGWff.js +0 -1
  41. package/dist/assets/EditorDrawer-CvCe9WeO.js +0 -2
  42. package/dist/assets/HideInsteadOfDeleteModal-3j9g-E9l.js +0 -1
  43. package/dist/assets/IconPickerModal-BLoDLbLR.js +0 -1
  44. package/dist/assets/ImportXmlModal-BD-L1QzJ.js +0 -1
  45. package/dist/assets/MonacoEditor-BMKRZv-g.js +0 -2
  46. package/dist/assets/NewButtonModal-COYXwEyk.js +0 -1
  47. package/dist/assets/NewGroupModal-boP_t1fI.js +0 -1
  48. package/dist/assets/NewTabModal-BI4afbC5.js +0 -1
  49. package/dist/assets/RuleEditorPanel-l8QnRFj6.js +0 -1
  50. package/dist/assets/ScriptView-BVyCmRvD.js +0 -1
  51. package/dist/assets/TabDisplayRulesPanel-gORq6MO7.js +0 -1
  52. package/dist/assets/TranslationsView-DubBATog.js +0 -1
  53. package/dist/assets/WebResourceBrowser-BATScmTw.js +0 -1
  54. package/dist/assets/XmlView-Bn4KlTw3.js +0 -2
  55. package/dist/assets/abap-DLDM7-KI.js +0 -1
  56. package/dist/assets/apex-DNDY2TF8.js +0 -1
  57. package/dist/assets/azcli-Y6nb8tq_.js +0 -1
  58. package/dist/assets/bat-BwHxbl9M.js +0 -1
  59. package/dist/assets/bicep-CFznDFnq.js +0 -2
  60. package/dist/assets/cameligo-Bf6VGUru.js +0 -1
  61. package/dist/assets/clojure-Dnu-v4kV.js +0 -1
  62. package/dist/assets/coffee-Bd8akH9Z.js +0 -1
  63. package/dist/assets/cpp-BbWJElDN.js +0 -1
  64. package/dist/assets/csharp-Co3qMtFm.js +0 -1
  65. package/dist/assets/csp-D-4FJmMZ.js +0 -1
  66. package/dist/assets/css-DdJfP1eB.js +0 -3
  67. package/dist/assets/css.worker-C_6RgliQ.js +0 -97
  68. package/dist/assets/cssMode-yNaVDuBb.js +0 -1
  69. package/dist/assets/cypher-cTPe9QuQ.js +0 -1
  70. package/dist/assets/dart-BOtBlQCF.js +0 -1
  71. package/dist/assets/dockerfile-BG73LgW2.js +0 -1
  72. package/dist/assets/ecl-BEgZUVRK.js +0 -1
  73. package/dist/assets/elixir-BkW5O-1t.js +0 -1
  74. package/dist/assets/flow9-BeJ5waoc.js +0 -1
  75. package/dist/assets/fluent-icons-CQEhzzaC.js +0 -1
  76. package/dist/assets/fluent-ui-BEjALNLO.js +0 -59
  77. package/dist/assets/freemarker2-CzWSO7cF.js +0 -3
  78. package/dist/assets/fsharp-PahG7c26.js +0 -1
  79. package/dist/assets/go-acbASCJo.js +0 -1
  80. package/dist/assets/graphql-BxJiqAUM.js +0 -1
  81. package/dist/assets/handlebars-BpG2O9CH.js +0 -1
  82. package/dist/assets/hcl-DtV1sZF8.js +0 -1
  83. package/dist/assets/html-Bm7ESfBq.js +0 -1
  84. package/dist/assets/html.worker-CLyYFd_g.js +0 -474
  85. package/dist/assets/htmlMode--CmpAV7s.js +0 -1
  86. package/dist/assets/index-6so8O90C.js +0 -136
  87. package/dist/assets/ini-Kd9XrMLS.js +0 -1
  88. package/dist/assets/java-CXBNlu9o.js +0 -1
  89. package/dist/assets/javascript-DYy3TIq5.js +0 -1
  90. package/dist/assets/json.worker-BggoxaER.js +0 -62
  91. package/dist/assets/jsonMode-DwsyQ3o1.js +0 -7
  92. package/dist/assets/julia-cl7-CwDS.js +0 -1
  93. package/dist/assets/kotlin-s7OhZKlX.js +0 -1
  94. package/dist/assets/less-9HpZscsL.js +0 -2
  95. package/dist/assets/lexon-OrD6JF1K.js +0 -1
  96. package/dist/assets/liquid-qkuWCPaY.js +0 -1
  97. package/dist/assets/lspLanguageFeatures-Cgd9CNvq.js +0 -4
  98. package/dist/assets/lua-Cyyb5UIc.js +0 -1
  99. package/dist/assets/m3-B8OfTtLu.js +0 -1
  100. package/dist/assets/markdown-BFxVWTOG.js +0 -1
  101. package/dist/assets/mdx-CtHfOclF.js +0 -1
  102. package/dist/assets/mips-CiqrrVzr.js +0 -1
  103. package/dist/assets/monaco-BIO15LCS.js +0 -1005
  104. package/dist/assets/monaco-DdLsZAcA.css +0 -1
  105. package/dist/assets/msdax-DmeGPVcC.js +0 -1
  106. package/dist/assets/mysql-C_tMU-Nz.js +0 -1
  107. package/dist/assets/objective-c-BDtDVThU.js +0 -1
  108. package/dist/assets/pascal-vHIfCaH5.js +0 -1
  109. package/dist/assets/pascaligo-DtZ0uQbO.js +0 -1
  110. package/dist/assets/perl-Ub6l9XKa.js +0 -1
  111. package/dist/assets/pgsql-BlNEE0v7.js +0 -1
  112. package/dist/assets/php-BBUBE1dy.js +0 -1
  113. package/dist/assets/pla-DSh2-awV.js +0 -1
  114. package/dist/assets/postiats-CocnycG-.js +0 -1
  115. package/dist/assets/powerquery-tScXyioY.js +0 -1
  116. package/dist/assets/powershell-COWaemsV.js +0 -1
  117. package/dist/assets/protobuf-Brw8urJB.js +0 -2
  118. package/dist/assets/pug-8SOpv6rk.js +0 -1
  119. package/dist/assets/python-CazlH6B-.js +0 -1
  120. package/dist/assets/qsharp-Bw9ernYp.js +0 -1
  121. package/dist/assets/r-j7ic8hl3.js +0 -1
  122. package/dist/assets/razor-BfGfB6aB.js +0 -1
  123. package/dist/assets/redis-Bu5POkcn.js +0 -1
  124. package/dist/assets/redshift-Bs9aos_-.js +0 -1
  125. package/dist/assets/restructuredtext-CqXO7rUv.js +0 -1
  126. package/dist/assets/ruby-zBfavPgS.js +0 -1
  127. package/dist/assets/rust-BzKRNQWT.js +0 -1
  128. package/dist/assets/sb-BBc9UKZt.js +0 -1
  129. package/dist/assets/scala-D9hQfWCl.js +0 -1
  130. package/dist/assets/scheme-BPhDTwHR.js +0 -1
  131. package/dist/assets/scss-CBJaRo0y.js +0 -3
  132. package/dist/assets/shell-DiJ1NA_G.js +0 -1
  133. package/dist/assets/solidity-Db0IVjzk.js +0 -1
  134. package/dist/assets/sophia-CnS9iZB_.js +0 -1
  135. package/dist/assets/sparql-CJmd_6j2.js +0 -1
  136. package/dist/assets/sql-ClhHkBeG.js +0 -1
  137. package/dist/assets/st-CHwy0fLd.js +0 -1
  138. package/dist/assets/swift-CnmFD0ga.js +0 -1
  139. package/dist/assets/systemverilog-Bs9z6M-B.js +0 -1
  140. package/dist/assets/tcl-Dm6ycUr_.js +0 -1
  141. package/dist/assets/tsMode-BZv6gTt6.js +0 -11
  142. package/dist/assets/twig-Csy3S7wG.js +0 -1
  143. package/dist/assets/typescript-BgDL1fzP.js +0 -1
  144. package/dist/assets/typespec-Btyra-wh.js +0 -1
  145. package/dist/assets/useReplaceWebResourceConfirm-DND-V0vw.js +0 -1
  146. package/dist/assets/useStableKeys-BkDn7til.js +0 -1
  147. package/dist/assets/vb-Db0cS2oM.js +0 -1
  148. package/dist/assets/wgsl-BTesnYfV.js +0 -298
  149. package/dist/assets/workers-BZ4mXA5s.js +0 -1
  150. package/dist/assets/xml-Cl6spsD4.js +0 -1
  151. package/dist/assets/yaml-El-x4GhS.js +0 -1
package/CHANGELOG.md CHANGED
@@ -9,6 +9,100 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.9.0-beta.2] - 2026-11-01
13
+
14
+ ### 🔧 Changed
15
+
16
+ - **The Insider icon's gold corner is bigger, two-tone and flush with the edge (#236).** Betas
17
+ show a gold corner on the tool icon. It was small and light, and a blue sliver showed between it
18
+ and the hexagon's edge. It's now about 1.5 times larger, sits on both edges, and is split on the
19
+ same diagonal as the blue in two golds (`#CC8A00` and `#F2A100`), so it reads at the 20–24 px
20
+ PPTB shows. FetchXML Studio and Dataverse Request Studio use the same stamp. Restart PPTB to see
21
+ it: PPTB keeps tool icons until it restarts.
22
+ - **The tool starts without loading the code editor (#118).** Monaco (about 4 MB) loaded with the
23
+ tool, before any editor opened. It now loads the first time you open the XML view, Compare, a
24
+ script, Import XML or the publish dialog's XML. It brings XML and JavaScript only: the other
25
+ languages and the CSS, HTML and JSON workers are gone, and the package is 3.3 MB smaller
26
+ (16.3 → 13.0 MB unpacked).
27
+
28
+ ### 🔧 Fixed
29
+
30
+ - **The pane resize handles work from the keyboard (#23).** Tab to the handle beside the left
31
+ pane, the Properties pane or the bottom panel, then use the arrow keys (Shift for bigger
32
+ steps). Screen readers announce which pane it sizes, its width or height, and how far it can
33
+ go in this window. Dragging a handle saved the pane
34
+ sizes on every mouse move; it now saves them at most every quarter second.
35
+ - **Screen readers get accurate roles on the Classic and Modern canvases (#23).** The Classic
36
+ canvas called itself a tree grid without rows or cells; its groups are now plain groups. The
37
+ selected button on both canvases is marked as current, instead of with an attribute buttons
38
+ don't support.
39
+ - **The Classic canvas works from the keyboard (#23).** Tabbing to a button didn't select it:
40
+ its group took the focus event and selected itself instead. The arrow keys didn't move between
41
+ buttons you can drag, because the drag handler replaced the button's own. Enter or Space
42
+ picks a button up to move it with the arrow keys, as before, and now keeps that button
43
+ selected (its group moved the selection to the group's first button). Escape cancels the move
44
+ without leaving the canvas stuck in drag mode.
45
+ - **The Structure pane's hint wraps inside its padding.** With no table chosen, the second line
46
+ of "Choose a table to see its tabs, groups and buttons." started at the pane's edge.
47
+
48
+ ### 🏗️ Technical
49
+
50
+ - **Accessibility lint (#23).** The `jsx-a11y` recommended rules are on, so CI fails on new
51
+ keyboard and screen-reader problems. The few deliberate exceptions (dialog autofocus, the
52
+ command palette's options, focusable tooltip triggers, the resize handles) are disabled on
53
+ their line with the reason.
54
+ - **Release workflow hardening (#250, as FetchXML Studio #188).**
55
+ - **Separate jobs:** `release.yml` is split into `build`, `publish` and `github-release`.
56
+ - The job that installs and runs the dependencies (`npm ci --ignore-scripts`, no cache, the
57
+ checks, the build) can only read the repository.
58
+ - Only `publish` can get the npm OIDC token, only for a tag push, and it installs no
59
+ project dependencies: it publishes the tarball `build` packed.
60
+ - Only `github-release` can write to the repository.
61
+ - **More checks before publishing:** the release build now also runs the runtime audit,
62
+ typecheck, lint and the package-contents check, so a tag on a commit that skipped CI can't
63
+ publish.
64
+ - **Pinned versions:** npm is pinned to 11.21.1 instead of `npm@latest`, and Node to 24.22.0.
65
+ The actions are pinned by commit SHA (checkout v7.0.1, setup-node v7.1.0, upload-artifact
66
+ v7.0.2, download-artifact v8.0.2). Each is at least 14 days old, the project's dependency
67
+ rule.
68
+ - **Rehearsal:** the workflow can run by hand as a rehearsal: every check and
69
+ `npm publish --dry-run`, with no npm token and no GitHub Release. A manual run never
70
+ publishes, even on a tag.
71
+ - **`latest` can't move back:** a stable tag gets `latest` only for main's own version line,
72
+ and a `support/X.Y` commit is checked first. Support branches merge forward into `main`, so
73
+ re-running an older line's release after that merge could have published it to `latest`.
74
+ - **CI:** uses `npm ci --ignore-scripts` and the same action pins, and doesn't keep the
75
+ checkout's token.
76
+ - **Releases check what they must update (#246, as FetchXML Studio #270).** A new
77
+ `check-release.mjs` runs in CI (every PR, and pushes to the long-lived branches) and in the
78
+ release build. It fails when any of these don't match `package.json`'s version:
79
+ - the version's shape (`X.Y.Z`, `X.Y.Z-beta.N` or `X.Y.Z-rc.N`);
80
+ - `package-lock.json`;
81
+ - the CHANGELOG (a dated `[X.Y.Z]` section with entries, under `[Unreleased]`);
82
+ - the version badge (`assets/badges/version.svg` must be what `npm run version-badge` writes);
83
+ - after the build, the bundled icon (the Insider icon for pre-releases).
84
+
85
+ The GitHub Release notes are now built from the CHANGELOG section, after a line on the channel
86
+ and the PPTB requirement, with GitHub's PR list after them. Before, they were the PR list
87
+ alone, replaced by hand. A rehearsal previews them in the run summary. RELEASING.md has a
88
+ table of what every release changes, and an *After every release* checklist (the npm tag, the
89
+ published icon, the tracking issue, the forward merge, deprecating the replaced version).
90
+ Forward merges keep the higher version.
91
+ - **Repository hygiene (#118).**
92
+ - **Dead code removed:** the unused PublishXml publish helpers (with their PublishAllXml
93
+ fallback), a second copy of the LocLabel XML builder, `groupTemplates.ts` (it listed
94
+ templates that don't exist), and five unused exports (`fetchPublisherPrefix`,
95
+ `isInsidePPTB`, `classicIdForMigratedCommand`, `isOverrideCustomAction`, `evaluateRule`).
96
+ - **A misleading comment corrected:** the generator's system-command filter doesn't keep
97
+ unchanged out-of-the-box commands out of a publish (the parser keeps their actions since
98
+ #42); `keepOnly` in `publishService` does.
99
+ - **Coverage:** `npm run test:coverage` (`@vitest/coverage-v8`), and CI writes the totals to
100
+ the run summary. It reports; it doesn't gate.
101
+ - **README:** removed features the tool doesn't have (the form ribbon scope selector, Power Fx
102
+ and Custom API actions, editing web resources in Monaco, the URL Action Composer) and the
103
+ old test counts; the roadmap points at the milestones.
104
+ - **CHANGELOG:** entries for 0.5.1 and 0.5.2.
105
+
12
106
  ## [0.9.0-beta.1] - 2026-11-01
13
107
 
14
108
  The first beta of 0.9.0 (npm `beta`): the UX overhaul in Fluent 2, and Edit mode.
@@ -1152,6 +1246,18 @@ in the desktop app and the VS Code extension. 0.5.x stays available for PPTB ver
1152
1246
  config (replaced, see above), coverage, the bundle analyzer and unused testing-library packages (12 dev dependencies
1153
1247
  in total).
1154
1248
 
1249
+ ## [0.5.2] - 2026-07-17
1250
+
1251
+ Republished 0.5.1 (same commit, `274eb2a`); no changes.
1252
+
1253
+ ## [0.5.1] - 2026-07-17
1254
+
1255
+ Published to npm before the repository had tags or CI.
1256
+
1257
+ - **Monaco works inside PPTB.** Its language workers are bundled with the tool, same-origin,
1258
+ instead of being fetched, which PPTB's content security policy blocks (`e8aaf9c`).
1259
+ - **npm packaging metadata** for the ToolBox (`274eb2a`).
1260
+
1155
1261
  ## [0.5.0] - 2026-07-16
1156
1262
 
1157
1263
  ### 🎉 First Beta Release
package/README.md CHANGED
@@ -38,14 +38,13 @@ reimagined with React 18, Fluent UI v9, and live Dataverse integration via
38
38
  - Command binding with action summary chips
39
39
  - Display rules + Enable rules pill lists with inline add/remove
40
40
  - Scaling summary (read-only: the tab's groups and scaling steps)
41
- - Advanced: form ribbon scope selector, `Mscrm.OpenRecordItem` override toggle, client-type filter shortcuts (Unified Interface evaluates as `Modern`; one filter per command)
41
+ - Advanced: `Mscrm.OpenRecordItem` override toggle, client-type filter shortcuts (Unified Interface evaluates as `Modern`; one filter per command)
42
42
  - Provenance notice — names the managed solution and publisher a button comes from
43
43
 
44
44
  ### ⚡ Command Editor
45
45
  - JavaScript function: library (with Browse… to Web Resource Browser), function name, positional CrmParameter editor
46
46
  - URL action: address, PassParams, WinMode, named CrmParameters with querystring key
47
- - **Power Fx expression** — inline Monaco editor (syntax-highlighted, word wrap) with variable hints (`ThisRecord`, `Selection`, `Self`) and async-rule note
48
- - Custom API / Web API action
47
+ - Power Fx and Custom API actions belong to modern commands (`appaction`), not the classic ribbon: they aren't offered, and an existing one shows as not supported ([#28](https://github.com/mohsinonxrm/pptb-mxrm-commandbar-studio/issues/28))
49
48
  - Enable rules + Display rules binding
50
49
  - References tab showing exact buttons + tab/group breadcrumb
51
50
  - Versions tab from history
@@ -85,12 +84,7 @@ reimagined with React 18, Fluent UI v9, and live Dataverse integration via
85
84
  ### 🌐 Web Resource Browser
86
85
  - Virtualized list with type filter, custom-only toggle, search
87
86
  - Upload new resource directly from the browser
88
- - Edit JS/CSS/XML files in Monaco
89
-
90
- ### 🔗 URL Action Composer
91
- - Base URL, PassParams (full 6-parameter table per MS docs), custom CrmParameters
92
- - Live URL preview; `&` → `&` escaping handled automatically
93
- - WinMode: Navigate / Dialog / Popup
87
+ - A command's JavaScript library opens in Monaco from the Command Editor (**View script** / **Edit script**)
94
88
 
95
89
  ### 📊 XML and Compare
96
90
  - Views of the editor drawer: the XML of your changes opens on the location you're on, one location per tab, in Monaco (read-only; **Import this XML** hands it to the import dialog)
@@ -124,6 +118,7 @@ reimagined with React 18, Fluent UI v9, and live Dataverse integration via
124
118
  - `Delete/Backspace` — Delete button (with OOB confirm)
125
119
  - `F2` — Inline rename tab / group
126
120
  - Arrow keys — navigate buttons on canvas
121
+ - Pane resize handles — Tab to one, then the arrow keys resize the pane (Shift for bigger steps)
127
122
 
128
123
  ### 💾 Persistence
129
124
  - Unpublished changes are saved as a draft in `localStorage` after every change, per org,
@@ -291,7 +286,7 @@ CBS runs in two modes:
291
286
  | **Zustand** | 5 | Global state (ribbons, selection, UI, session) |
292
287
  | **fflate** | 0.8 | ZIP compression for solution package + ribbon XML decompression |
293
288
  | **@pptb/types** | 1.2.7 | Power Platform ToolBox host API types (`window.dataverseAPI`, `window.toolboxAPI`) |
294
- | **Vitest** | 3 | Test runner — 148 tests across 8 suites |
289
+ | **Vitest** | 5 | Test runner (`npm test`) |
295
290
 
296
291
  ---
297
292
 
@@ -337,14 +332,15 @@ src/
337
332
  sessionStore.ts — Solutions, entities, connection, publisher prefix
338
333
  runtimeLogStore.ts — Console tab entries
339
334
  utils/
340
- ruleEngine.ts — summarizeRule() + evaluateRule() for all 30 kinds
335
+ ruleEngine.ts — summarizeRule(): a rule in plain English, for all 30 kinds
336
+ monacoSetup.ts — Monaco (XML and JavaScript only), loaded with the first editor
341
337
  idGenerator.ts — Publisher-prefixed unique ribbon IDs
342
338
  webResourceBrowserCallback.ts — Module-level callback registry for WRB selection
343
339
  ribbonProvenance.ts — applyProvenanceToRibbons + heuristicOrigin
344
340
  monacoCompletions.ts — $LocLabels: / $webresource: / Command= completions
345
341
  types/
346
342
  ribbon.ts — Full domain model: RibbonButton, RuleStep (30 kinds), …
347
- __tests__/ — 148 Vitest tests
343
+ __tests__/ — Vitest tests (`npm test`)
348
344
  __fixtures__/ — ribbon/account-full.xml, all-rule-kinds.xml, ribbondiff/…
349
345
  ```
350
346
 
@@ -369,9 +365,11 @@ style messages (`feat:`, `fix:`, `chore:` …).
369
365
 
370
366
  ## 📋 Roadmap
371
367
 
368
+ What's planned is on the [milestones](https://github.com/mohsinonxrm/pptb-mxrm-commandbar-studio/milestones). Longer-term ideas:
369
+
372
370
  - [x] ~~ClassicRibbon drag migration to `@dnd-kit` with `DragOverlay` ghost~~ ✅ shipped in 0.5.0
373
371
  - [ ] `QueueUpdateRibbonClientMetadata` for targeted ribbon-only publish (vs. broad `publishCustomizations`)
374
- - [ ] Power Fx LSP / language server integration
372
+ - [ ] Modern commands with JavaScript actions (v1.1.0; Power Fx stays out of scope)
375
373
  - [ ] Import error line highlighting in Monaco
376
374
  - [ ] Accessibility audit — verify full WCAG 2.1 AA compliance against spec §28
377
375
  - [ ] ClassicRibbon button drag: migrate from `useDraggable` to `useSortable` for live in-place reordering animation
@@ -0,0 +1,36 @@
1
+ import{r as $,j as n,a6 as se,a7 as te,a8 as ke,c as D,B as Ge,F as Ne,ar as Bn,m as Vn,t as I,W as re,dY as Sn,k as ce,ao as us,a9 as hs,e3 as ms,e4 as ve,e5 as Re,e6 as Se,eP as ps,d as $n,eQ as bs,dO as gs,ec as fs,dX as ys,e0 as xs,N as ws,cH as Cs,aq as js,am as vs,al as Rs,ap as Ss,ai as $s,at as Is}from"./fluent-ui-CQyNN9H3.js";import{p as $e,g as ks,e as Ns,d as Ps,m as _e,f as Ts,h as As,j as Es,k as Ds,n as Ls,l as Qe,o as zs,q as Ms,r as Os,s as Us,t as Ye,v as Xs,w as Bs,x as Vs,y as In,z as qs,A as Ws,B as He,C as Fs,D as _s,E as qn,F as en,G as Pe,H as Hs,J as Ks,K as kn,L as Gs,M as Ke,N as Ys,O as Nn,P as B,Q as Js,R as Wn,S as W,T as Fn,U as Zs,V as Je,W as Qs,b as Pn,a as X,X as et,Y as Ie,Z as nt,_ as st,$ as tt,a0 as it,a1 as Tn}from"./index-DRTwBo4g.js";import{M as ot}from"./MonacoEditor-DweI16yt.js";import{w as at,v as _n}from"./xmlValidator-CnbyWxHe.js";import"./preload-helper-PPVm8Dsz.js";import"./dnd-iy5K5XAJ.js";import"./ruleKinds-BKTUiZ1-.js";import"./crmParameters-rgfZhhzN.js";let An=0;async function nn(e){const s=typeof window<"u"?window.toolboxAPI:void 0;An++===0&&await En(()=>s?.preventClose?.());try{return await e()}finally{--An===0&&await En(()=>s?.releasePreventClose?.())}}const lt=2e3;async function En(e){let s;try{await Promise.race([e(),new Promise(i=>s=setTimeout(i,lt))])}catch{}finally{clearTimeout(s)}}function pe(e,s){const i=e.match(new RegExp(`\\s${s}="([^"]*)"`));return i?i[1]:null}function Dn(e,s,i){const o=e.indexOf(i,s);return e.slice(s,o===-1?void 0:o).match(/<result\s[^>]*>/g)??[]}function Ln(e){const s=e.find(i=>pe(i,"result")!=="success");if(s){const i=pe(s,"errorcode")??"",o=pe(s,"errortext")??"unknown error";return{ok:!1,message:`Dataverse rejected the ribbon (${i}): ${o}`}}return null}function rt(e,s){if(!e)return{ok:!1,message:"The import job returned no result data, so the ribbon import could not be verified."};if(s.kind==="application"){const a=e.search(/<ribbon\s[^>]*processed="true"/);return a===-1?{ok:!1,message:"Import completed, but Dataverse did not process the application ribbon."}:Ln(Dn(e,a,"</ribbon>"))??{ok:!0,message:"Application ribbon imported."}}const i=new Set(s.names.filter(Boolean).map(a=>a.toLowerCase())),o=/<entityRibbon\s[^>]*>/g;let l;for(;l=o.exec(e);){const a=(pe(l[0],"id")??"").toLowerCase();if(i.has(a))return pe(l[0],"processed")!=="true"?{ok:!1,message:`Dataverse did not process the ribbon for ${a}.`}:Ln(Dn(e,l.index,"</entityRibbon>"))??{ok:!0,message:`Ribbon for ${a} imported.`}}return{ok:!1,message:`Import completed, but Dataverse did not apply a ribbon for ${s.names.join(" / ")} (no entityRibbon result in the import job). Nothing was changed.`}}const K=window.dataverseAPI;async function ct(e,s,i){return await i("The import"),K.execute({operationName:"ImportSolution",operationType:"action",parameters:{CustomizationFile:e,ImportJobId:s,OverwriteUnmanagedCustomizations:!0,PublishWorkflows:!1}})}async function dt(e,s){await s("Publishing");const i=e.map(o=>`<entity>${B(o)}</entity>`).join("");return K.execute({operationName:"PublishXml",operationType:"action",parameters:{ParameterXml:`<importexportxml><entities>${i}</entities></importexportxml>`}})}function zn(e){const s=e.data?.progress;return!!(typeof s=="object"&&s!==null&&s.completed===!0||typeof e.progress=="number"&&e.progress>=100||typeof s=="number"&&s>=100||e.completedon||e.data?.completedon||e.statuscode===30)}async function Hn(e){const s=e.entity?.logicalName??"{!EntityLogicalName}",i={deletedContainerIds:e.plan.deletedContainerIds??[],movedButtons:e.plan.movedButtons??[],editedLocLabelIds:e.plan.editedLocLabelIds??[],editedTabIds:e.plan.editedTabIds??[],resequencedTabs:e.plan.resequencedTabs??[],resequencedGroups:e.plan.resequencedGroups??[]},o=e.locLabels.filter(r=>i.editedLocLabelIds.includes(r.id)),l=e.languageCode??1033;for(const r of e.plan.renamedLabels??[]){const h=o.find(S=>S.id===r.id)??e.locLabels.find(S=>S.id===r.id),j=[{languageCode:l,description:r.text},...(h?.titles??[]).filter(S=>S.languageCode!==l)],R=o.findIndex(S=>S.id===r.id);R>=0?o[R]={id:r.id,titles:j}:o.push({id:r.id,titles:j})}let a=o.length?$e(`<RibbonDiffXml><LocLabels>${o.map(ks).join("")}</LocLabels></RibbonDiffXml>`):Ns();for(const r of e.locations){const h=Ps({current:r.current,baseline:r.baseline,commands:e.commands,enableRules:e.enableRules,displayRules:e.displayRules,locLabels:e.locLabels,entityLogicalName:s,location:r.current.location,languageCode:e.languageCode});a=_e(a,$e(h))}const c=[],u=[];for(const r of e.locations)for(const h of r.current.tabs){if(!i.editedTabIds.includes(h.id))continue;if(h.tabDisplayRules.length>0){const R=Ts(h,e.entity===null);R&&u.push(R)}const j=new Set(h.tabDisplayRules.map(R=>R.tabCommand));for(const R of r.baseline.tabs.find(S=>S.id===h.id)?.tabDisplayRules??[])j.has(R.tabCommand)||c.push(R.tabCommand)}u.length>0&&(a=_e(a,$e(`<RibbonDiffXml><RuleDefinitions><TabDisplayRules>${u.join("")}</TabDisplayRules></RuleDefinitions></RibbonDiffXml>`)));const y=[...e.commands.filter(r=>e.plan.editedCommandIds.includes(r.id)).map(As)],T={enable:e.enableRules.filter(r=>e.plan.editedEnableRuleIds.includes(r.id)).map(Ds),display:e.displayRules.filter(r=>e.plan.editedDisplayRuleIds.includes(r.id)).map(Es)};(y.length||T.enable.length||T.display.length)&&(a=_e(a,$e(`<RibbonDiffXml><CommandDefinitions>${y.join("")}</CommandDefinitions><RuleDefinitions><DisplayRules>${T.display.join("")}</DisplayRules><EnableRules>${T.enable.join("")}</EnableRules></RuleDefinitions></RibbonDiffXml>`)));const P=(r,h)=>{for(const j of Array.from(r.keys()))h.includes(j)||r.delete(j)},k=e.locations.flatMap(r=>r.current.tabs.filter(h=>!r.baseline.tabs.some(j=>j.id===h.id)).map(Ls));P(a.commandDefinitions,[...e.plan.editedCommandIds,...k]),P(a.enableRules,e.plan.editedEnableRuleIds),P(a.displayRules,e.plan.editedDisplayRuleIds);const m=await Qe(e.entity?.logicalName??null),v=zs(m),b=e.plan.deletedButtonIds.filter(r=>!v.has(r));if(b.length>0)throw new Error(`Can't delete ${b.join(", ")}: not defined in this table's unmanaged customizations (it comes from a managed solution or the platform). Undo the delete and hide the button instead.`);const x=Ms(m),g=i.deletedContainerIds.filter(r=>!x.has(r));if(g.length>0)throw new Error(`Can't delete ${g.join(", ")}: not added by this table's unmanaged customizations (it comes from a managed solution or the platform). Undo the delete.`);const p=i.movedButtons.filter(r=>!v.has(r.id)).map(r=>r.id);if(p.length>0)throw new Error(`Can't move ${p.join(", ")}: not defined in this table's unmanaged customizations. Undo the move.`);const q=Os(m),G=(e.plan.uncustomisedCommandIds??[]).filter(r=>m.commandDefinitions.has(r)&&!Us(r,q));if(G.length>0)throw new Error(`Can't uncustomise ${G.join(", ")}: it is your own command (your customizations' buttons use it and no other solution defines it), so removing it would leave those buttons without a command. Undo the uncustomise.`);const Y=new Set;for(const r of e.locations)for(const h of r.current.tabs)for(const j of h.groups)for(const R of Ye(j))for(const S of Xs(R))Y.add(S);const U=e.plan.uncustomisedCommandIds??[],V=new Set,J=new Set;for(const r of e.commands)if(!(!Y.has(r.id)||U.includes(r.id))){r.enableRules.forEach(h=>V.add(h)),r.displayRules.forEach(h=>J.add(h));for(const h of r.rawRuleRefs??[]){const j=/^\s*<(EnableRule|DisplayRule)\b[^>]*?\sId="([^"]+)"/.exec(h.xml);j&&(j[1]==="EnableRule"?V:J).add(j[2])}}let C=Bs(m,a,{retainedCommandIds:Y,editedCommandIds:e.plan.editedCommandIds,editedEnableRuleIds:e.plan.editedEnableRuleIds,editedDisplayRuleIds:e.plan.editedDisplayRuleIds,deletedControlIds:e.plan.deletedButtonIds,unhiddenControlIds:e.plan.unhiddenButtonIds,deletedContainerIds:i.deletedContainerIds,movedControls:i.movedButtons,resequencedContainers:[...i.resequencedTabs,...i.resequencedGroups],removedTabCommands:c,uncustomisedCommandIds:U,retainedEnableRuleIds:V,retainedDisplayRuleIds:J});for(const r of e.plan.renamedLabels??[])r.newLabel&&(C=Vs(C,r.containerId,`$LocLabels:${r.id}`));const d=new Set([...In(m),...In(C)].map(r=>r.id)),N={};for(const r of e.locations)for(const[h,j]of Object.entries(r.baseline.scalingByTab??{}))N[h]={maxSizes:j.maxSizes.filter(R=>!d.has(R.id)).map(R=>R.sequence),scales:j.scales.filter(R=>!d.has(R.id)).map(R=>R.sequence)};const A=qs(C,N);if(A.problems.length>0)throw new Error(`Not published: ${A.problems.join("; ")}.`);return C=A.parts,{scalingChanges:A.changes,xml:Fs(C),parts:C,elementCount:He(C),preservedCount:He(m),changedCount:He(a),changedKeys:Ws(m,C),newKeys:Object.keys(C).flatMap(r=>Array.from(C[r].keys()).filter(h=>!m[r].has(h)).map(h=>`${r}:${h}`)),layerDefinitionIds:{commandIds:Array.from(m.commandDefinitions.keys()),enableRuleIds:Array.from(m.enableRules.keys()),displayRuleIds:Array.from(m.displayRules.keys())},layer:m}}function Kn(e,s){const i=[],o={},l={},a={},c={},u=new Set,y=new Set,T=new Set;for(const{current:m,baseline:v}of e.locations)for(const b of[v,m])for(const x of b.tabs)for(const g of x.groups)for(const p of Ye(g))for(const q of p.menu?.sections??[])T.add(q.controlsId);for(const{current:m,baseline:v}of e.locations){Object.assign(a,v.templateLayouts);for(const b of v.tabs){i.push(b.id),b.label&&(c[b.id]={Title:b.label});for(const x of b.groups){u.add(x.id),i.push(x.id),x.label&&(c[x.id]={Title:x.label,Label:x.label});for(const g of Ye(x))i.push(g.id),g.source&&(c[g.id]=g.source.attributes)}}for(const b of m.tabs)for(const x of b.groups)y.add(x.id);for(const b of[v,m])for(const x of b.tabs)for(const g of x.groups)g.template&&(l[g.id]=g.template)}const P=m=>u.has(m.groupId)&&!y.has(m.groupId);for(const{baseline:m}of e.locations)for(const[v,b]of Object.entries(m.scalingByTab??{}))o[v]={...b,maxSizes:b.maxSizes.filter(x=>!P(x)),scales:b.scales.filter(x=>!P(x))};const k=(m,v)=>{if(!m)return;const b=new Set(v??[]);return m.map(x=>x.id).filter(x=>!b.has(x))};return{changedKeys:s.changedKeys,newKeys:s.newKeys,commands:e.commands,known:{commandIds:k(e.baselineCommands,s.layerDefinitionIds?.commandIds),enableRuleIds:k(e.baselineEnableRules,s.layerDefinitionIds?.enableRuleIds),displayRuleIds:k(e.baselineDisplayRules,s.layerDefinitionIds?.displayRuleIds),elementIds:i},loadedAttributes:c,publisherPrefix:e.publisherPrefix,tabScaling:o,groupTemplates:l,templateLayouts:a,menuControlsIds:T,...e.entity?{places:{entityLogicalName:e.entity.logicalName,tabByCollection:Object.fromEntries(_s(e.locations.map(m=>m.baseline),e.entity.logicalName))}}:{}}}function ut(e,s){return new Promise((i,o)=>{const l=setTimeout(()=>o(new Error(`it didn't finish within ${Math.round(s/1e3)} s`)),s);e.then(a=>{clearTimeout(l),i(a)},a=>{clearTimeout(l),o(a)})})}async function Mn(e,s={}){const i=await Hn(e),o=Kn(e,i),l=[],a=at(i.parts);if(s.lookupWebResources&&a.length>0)try{o.webResources=await s.lookupWebResources(a)}catch(c){l.push({severity:"warning",code:"webresource-lookup",message:`Couldn't check the ${a.length} referenced web resource(s): ${c instanceof Error?c.message:String(c)}`})}return{findings:[..._n(i.parts,o),...l],xml:i.xml}}async function ht(e,s,i={}){const o=i.attempts??3,l=i.contentKeys??[];let a={missing:[],unexpected:[],differing:[]};for(let u=0;u<o;u++){u>0&&await new Promise(y=>setTimeout(y,i.delayMs??5e3));try{a=Wn(s,await Qe(e),{contentKeys:l})}catch(y){return{ok:!1,missing:[],unexpected:[],differing:[],message:`Couldn't read the published ribbon layer to verify it (${y instanceof Error?y.message:String(y)}).`}}if(a.missing.length===0&&a.unexpected.length===0&&a.differing.length===0){const y=l.length;return{ok:!0,...a,message:"Verified: the published ribbon layer has every element that was imported"+(y>0?`, and the ${y} element(s) this publish changed have the imported content.`:".")}}}const c=u=>u.slice(0,5).join(", ")+(u.length>5?", …":"");return{ok:!1,...a,message:"The published ribbon layer doesn't match what was imported"+(a.missing.length?`; missing: ${c(a.missing)}`:"")+(a.unexpected.length?`; unexpected: ${c(a.unexpected)}`:"")+(a.differing.length?`; different content: ${c(a.differing)}`:"")+". Reload the table and check before publishing again."}}class Ze extends Error{constructor(s,i,o=!1){const l=o?"another solution import ran in the environment meanwhile, and what it changed may not be published yet":Gn(i);super(o?`${s}'s ribbon customizations may have changed in Dataverse since you started publishing: ${l}. Importing could overwrite that change, so nothing was imported. Publish again: the table is published first, so the change is kept.`:`${s}'s ribbon customizations changed in Dataverse since you started publishing (${l}): other ribbon changes for it were published meanwhile, from another session, tool or solution import. Importing would overwrite that change, so nothing was imported. Reload the table to get the change, then publish again.`),this.scopeLabel=s,this.changes=i,this.importRan=o,this.name="RibbonLayerChangedError",this.summary=l}scopeLabel;changes;importRan;summary}function Gn(e){const s=i=>i.slice(0,5).join(", ")+(i.length>5?", …":"");return[e.unexpected.length?`added: ${s(e.unexpected)}`:"",e.missing.length?`removed: ${s(e.missing)}`:"",e.differing.length?`changed: ${s(e.differing)}`:""].filter(Boolean).join("; ")}function mt(e){const s=e instanceof Error?e.message:String(e);return/there is (?:another|a previous) \[(\w+)\] running/i.exec(s)?.[1]??null}const pt=e=>Object.keys(e).flatMap(s=>Array.from(e[s].keys()).map(i=>`${s}:${i}`));function Yn(e,s){const i=[],o=[],l=[];for(const a of Object.keys(e)){for(const[c,u]of e[a]){const y=s[a].get(c);y===void 0?i.push(`${a}:${c}`):y!==u&&l.push(`${a}:${c}`)}for(const c of s[a].keys())e[a].has(c)||o.push(`${a}:${c}`)}return{missing:i,unexpected:o,differing:l}}const Jn=e=>e.missing.length+e.unexpected.length+e.differing.length>0;async function bt(e,s,i,o){const l=o.kind==="imported"?o.attempts??3:1;let a={missing:[],unexpected:[],differing:[]};for(let c=0;c<l;c++){c>0&&o.kind==="imported"&&await new Promise(y=>setTimeout(y,o.delayMs??5e3));const u=await Qe(e);if(a=o.kind==="read"?Yn(i,u):Wn(i,u,{contentKeys:pt(i)}),!Jn(a))return}throw new Ze(s,a)}function On(e,s){return nn(()=>gt(e,s)).finally(()=>qn({afterPublish:!0}))}async function gt(e,s){const i=e.guard??en(),o=Pe.getState(),l=e.entity?e.entity.logicalName:"Application ribbon",a={onProgress:s,...e.busy},c=e.entity===null;if(c&&!e.ribbonCustomizationIds?.length)throw new Error("The selected solution does not contain Application Ribbons. Add it in make.powerapps.com (Solutions → your solution → Add existing → Application Ribbons) and reload the solution.");const u=async(d="Publishing customizations…")=>{s?.(d),await Nn("Publish",async()=>{c?(await i("Publishing"),await K.execute({operationName:"PublishXml",operationType:"action",parameters:{ParameterXml:"<importexportxml><ribbons><ribbon></ribbon></ribbons></importexportxml>"}})):await dt([e.entity.logicalName],i)},a)},y=e.languageCode??await Hs(),T=async d=>{s?.(`Reading existing ribbon customizations for ${l}…`),d&&o.logInfo("publish",`Reading unmanaged ribbon layer for ${l}.`);const N=await Hn({...e,languageCode:y}),A=_n(N.parts,Kn({...e,publisherPrefix:e.solution.publisherPrefix},N)),r=A.filter(h=>h.severity==="error");if(d||r.length>0){o.logInfo("publish",`RibbonDiffXml for ${l}: ${N.preservedCount} existing element(s) preserved, ${N.changedCount} element(s) from this session, ${N.elementCount} total.`);for(const h of N.scalingChanges)o.logWarn("publish",Ys(h));for(const h of A)h.severity==="warning"&&o.logWarn("publish",h.message)}if(r.length>0){for(const h of r)o.logError("publish",h.message);throw new Error(`The pre-publish check found ${r.length} error(s), so nothing was imported: `+r.map(h=>h.message).join("; "))}return N},P=e.publishCustomizations!==!1?await T(!1):null;s?.("Checking that no other solution operation is running…"),await Ks(a);const k=await xt(e.solution);let m=!1;const v=d=>(P&&!m&&d instanceof Error&&(d.message+=` (${l} was published first, so customizations imported elsewhere for it and not yet published are now published.)`),d);if(P){o.logInfo("publish",`Publishing ${l} first, so ribbon changes imported elsewhere but not yet published are kept.`);try{await u(`Publishing ${l} first (keeps changes imported elsewhere but not published)…`)}catch(d){throw d instanceof Error&&(d.message=`Publishing ${l} first failed, so nothing was imported: ${d.message}`),d}}let b;try{b=await T(!0)}catch(d){throw P&&d instanceof Error&&!d.message.startsWith("The pre-publish check")&&(d.message=`${l}'s customizations changed when it was published first (changes imported elsewhere and not yet published): ${d.message} Reload the table to get them, then publish again.`),v(d)}if(P){const d=Yn(P.layer,b.layer);Jn(d)&&o.logInfo("publish",`Publishing ${l} first published ribbon changes imported elsewhere (${Gn(d)}); they are kept.`)}const x=e.entity?.schemaName||e.entity?.logicalName||"",g=c?kn({applicationRibbonDiffXml:b.xml}):kn({entities:[{schemaName:x,localizedName:e.entity?.displayName||x,ribbonDiffXml:b.xml}]}),p=c?[{type:50,schemaName:":RibbonDiffXml",behavior:0}]:[{type:1,schemaName:e.entity.logicalName,behavior:2}],q=jt({...e.solution,languageCode:y,rootComponents:p,details:k});s?.("Packaging solution ZIP…");const G=Gs({"customizations.xml":Ke(g),"solution.xml":Ke(q),"[Content_Types].xml":Ke('<?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 Y="";for(let d=0;d<G.length;d++)Y+=String.fromCharCode(G[d]);const U=btoa(Y),V=async(d,N)=>{s?.(`Importing ${l} ribbon${d}…`);const A=crypto.randomUUID();o.logInfo("publish",`Importing solution${d} (import job ${A})…`);let r=!1;await Nn("Import",async()=>{if(await i("Importing"),r)throw new Ze(l,{missing:[],unexpected:[],differing:[]},!0);await bt(e.entity?.logicalName??null,l,N.layer,N.as);try{await ct(U,A,i)}catch(_){throw Js(_)&&mt(_)?.toLowerCase()==="import"&&(r=!0),_}m=!0},a);const h=150,j=2e3;let R=await K.getImportJobStatus(A),S=0;for(;!zn(R)&&S<h;)await new Promise(_=>setTimeout(_,j)),R=await K.getImportJobStatus(A),S++,S%10===0&&s?.(`Still importing… (${S*2}s elapsed)`);if(!zn(R))throw new Error(`Solution import did not complete within ${h*j/1e3} seconds. Check Solutions › History for import job ${A}.`);s?.("Verifying the import…");const F=await K.retrieve("importjob",A,["data"]),Z=rt(F.data,c?{kind:"application"}:{kind:"entity",names:[x,e.entity.logicalName]});if(!Z.ok)throw o.logError("publish",Z.message),new Error(Z.message);return o.logInfo("publish",Z.message),A};let J;try{J=await V("",{layer:b.layer,as:{kind:"read"}})}catch(d){throw v(d)}let C;if(e.publishCustomizations!==!1){await u();{o.logInfo("publish","Refreshing Unified Interface command-bar metadata (second import of the same package)…");try{await V(" (refreshing Unified Interface metadata)",{layer:b.parts,as:{kind:"imported",delayMs:e.verifyDelayMs}}),await u()}catch(d){if(d instanceof Ze)C={ok:!1,...d.changes,message:`Your changes were imported and published, but ${l}'s ribbon customizations changed in Dataverse after that (${d.summary}): other changes were published meanwhile. They weren't imported a second time to refresh Unified Interface's command-bar metadata, since that would overwrite the other change, so new or changed buttons may not appear in the app until the table's ribbon is published again. Reload the table to see the other change.`},o.logWarn("publish",C.message);else throw new Error(`Your changes were imported and published, but refreshing Unified Interface's command-bar metadata failed (${d instanceof Error?d.message:String(d)}). New or changed buttons may not appear in the app until you publish again.`)}}C||(s?.("Verifying the published ribbon…"),C=await ht(e.entity?.logicalName??null,b.parts,{delayMs:e.verifyDelayMs,contentKeys:b.changedKeys}),C.ok?o.logInfo("publish",C.message):o.logWarn("publish",C.message))}else o.logWarn("publish","Imported without publishing. New or changed buttons appear in Unified Interface only after you publish from Command Bar Studio (which re-imports once to refresh the command-bar metadata).");return s?.(e.publishCustomizations!==!1?`${l} ribbon published.`:`${l} ribbon imported (not published).`),{elementCount:b.elementCount,preservedCount:b.preservedCount,importJobId:J,verification:C,parts:b.parts,changedKeys:b.changedKeys}}function ft(e,s){return nn(()=>yt(e,s)).finally(()=>qn({afterPublish:!0}))}async function yt(e,s){const i=s?.guard??en(),o=Pe.getState(),l=s?.pollIntervalMs??2e3,a=s?.timeoutMs??600*1e3;e?.("Starting asynchronous publish (PublishAllXmlAsync)..."),o.logInfo("publish","Calling PublishAllXmlAsync action."),await i("Publishing");const u=(await K.execute({operationName:"PublishAllXmlAsync",operationType:"action"}))?.AsyncOperationId;if(!u)throw new Error("PublishAllXmlAsync did not return AsyncOperationId.");o.logInfo("publish",`PublishAllXmlAsync job id: ${u}`),e?.("Async publish job started. Waiting for completion...");const y=Date.now();let T=0,P;for(;Date.now()-y<a;){T+=1;const k=await K.retrieve("asyncoperation",u,["asyncoperationid","statecode","statuscode","name","message","friendlymessage","completedon"]);if(P=k.statuscode,k.statecode===3||!!k.completedon){if(typeof k.statuscode=="number"&&k.statuscode!==30){const v=k.friendlymessage||k.message||`statuscode=${k.statuscode}`;throw new Error(`Asynchronous publish failed: ${v}`)}return e?.("Asynchronous publish completed successfully."),o.logInfo("publish",`PublishAllXmlAsync completed in ${T} poll(s).`),{asyncOperationId:u,statusCode:k.statuscode}}e?.(`Waiting for async publish job... (poll ${T})`),await new Promise(v=>setTimeout(v,l))}throw new Error(`Asynchronous publish timed out after ${Math.round(a/1e3)} seconds (last status: ${P??"unknown"}).`)}const Zn=[["AddressTypeCode","addresstypecode"],["City","city"],["County","county"],["Country","country"],["Fax","fax"],["FreightTermsCode","freighttermscode"],["Latitude","latitude"],["Line1","line1"],["Line2","line2"],["Line3","line3"],["Longitude","longitude"],["Name","name"],["PostalCode","postalcode"],["PostOfficeBox","postofficebox"],["PrimaryContactName","primarycontactname"],["ShippingMethodCode","shippingmethodcode"],["StateOrProvince","stateorprovince"],["Telephone1","telephone1"],["Telephone2","telephone2"],["Telephone3","telephone3"],["UPSZone","upszone"],["UTCOffset","utcoffset"],["UTCConversionTimeZoneCode","utcconversiontimezonecode"]];async function xt(e){let s;try{s=(await K.queryData(`solutions?$select=description&$expand=publisherid&$filter=uniquename eq '${e.uniqueName.replace(/'/g,"''")}'`)).value?.[0]}catch(c){throw new Error(`Couldn't read solution ${e.uniqueName} and its publisher (${c instanceof Error?c.message:String(c)}), so nothing was imported: an import without them would clear the publisher's details.`)}const i=s?.publisherid;if(!s||!i)throw new Error(`Couldn't read solution ${e.uniqueName} and its publisher, so nothing was imported: an import without them would clear the publisher's details.`);const o=i.customizationoptionvalueprefix;if(typeof o!="number")throw new Error(`Couldn't read the option-value prefix of publisher ${e.publisherUniqueName}, so nothing was imported: a wrong one would change the publisher.`);const l=c=>typeof c=="string"?c:"",a=[1,2].map(c=>Object.fromEntries(Zn.map(([,u])=>[u,i[`address${c}_${u}`]]).filter(([,u])=>u!=null&&u!==""))).map((c,u)=>({number:u+1,...c}));return{solutionDescription:l(s.description),publisherDescription:l(i.description),publisherEmail:l(i.emailaddress),publisherWebsite:l(i.supportingwebsiteurl),publisherOptionValuePrefix:o,publisherAddresses:a.filter(c=>Object.keys(c).length>1)}}const wt=e=>B(e).replace(/\r/g,"&#xD;").replace(/\n/g,"&#xA;").replace(/\t/g,"&#x9;"),Un=(e,s)=>e?`<Descriptions>
2
+ <Description description="${wt(e)}" languagecode="${s}"/>
3
+ </Descriptions>`:"<Descriptions/>",Ct=e=>e.length===0?"<Addresses/>":`<Addresses>${e.map(s=>`
4
+ <Address>
5
+ <AddressNumber>${s.number}</AddressNumber>${Zn.filter(([,i])=>i in s).map(([i,o])=>`
6
+ <${i}>${B(String(s[o]))}</${i}>`).join("")}
7
+ </Address>`).join("")}
8
+ </Addresses>`;function jt(e){const s=e.publisherUniqueName?.trim()||"DefaultPublisher",i=e.publisherName?.trim()||s,o=e.publisherPrefix?.trim()||"new",l=e.languageCode||1033,a=e.friendlyName?.trim()||e.uniqueName,c=e.rootComponents.length===0?"<RootComponents/>":`<RootComponents>
9
+ ${e.rootComponents.map(u=>{const y=[`type="${u.type}"`];return u.schemaName&&y.push(`schemaName="${B(u.schemaName)}"`),u.id&&y.push(`id="{${B(u.id)}}"`),y.push(`behavior="${u.behavior}"`),`<RootComponent ${y.join(" ")} />`}).join(`
10
+ `)}
11
+ </RootComponents>`;return`<?xml version="1.0" encoding="utf-8"?>
12
+ <ImportExportXml version="9.1.0.0" SolutionPackageVersion="9.1" languagecode="${l}" generatedBy="CommandBarStudio">
13
+ <SolutionManifest>
14
+ <UniqueName>${B(e.uniqueName)}</UniqueName>
15
+ <LocalizedNames>
16
+ <LocalizedName description="${B(a)}" languagecode="${l}"/>
17
+ </LocalizedNames>
18
+ ${Un(e.details.solutionDescription,l)}
19
+ <Version>${B(e.version)}</Version>
20
+ <Managed>0</Managed>
21
+ <Publisher>
22
+ <UniqueName>${B(s)}</UniqueName>
23
+ <LocalizedNames>
24
+ <LocalizedName description="${B(i)}" languagecode="${l}"/>
25
+ </LocalizedNames>
26
+ ${Un(e.details.publisherDescription,l)}
27
+ <EMailAddress>${B(e.details.publisherEmail)}</EMailAddress>
28
+ <SupportingWebsiteUrl>${B(e.details.publisherWebsite)}</SupportingWebsiteUrl>
29
+ <CustomizationPrefix>${B(o)}</CustomizationPrefix>
30
+ <CustomizationOptionValuePrefix>${e.details.publisherOptionValuePrefix}</CustomizationOptionValuePrefix>
31
+ ${Ct(e.details.publisherAddresses)}
32
+ </Publisher>
33
+ ${c}
34
+ <MissingDependencies/>
35
+ </SolutionManifest>
36
+ </ImportExportXml>`}const vt=Vn({root:{display:"flex",flexDirection:"column",gap:I.spacingVerticalS},box:{display:"grid",gridTemplateColumns:"auto 1fr",columnGap:I.spacingHorizontalM,rowGap:I.spacingVerticalXS,padding:`${I.spacingVerticalS} ${I.spacingHorizontalM}`,backgroundColor:I.colorNeutralBackground3,borderRadius:I.borderRadiusMedium},label:{color:I.colorNeutralForeground3},value:{display:"flex",flexWrap:"wrap",alignItems:"center",columnGap:I.spacingHorizontalS,minWidth:0},secondary:{color:I.colorNeutralForeground3,wordBreak:"break-all"}});function Rt({rows:e,confirmWord:s,onConfirmationChange:i,disabled:o}){const l=vt(),[a,c]=$.useState({status:"loading"}),[u,y]=$.useState(""),T=W(p=>p.environment),P=W(p=>p.connectionUrl),k=W(p=>p.connectionVersion);$.useEffect(()=>{let p=!0;return c({status:"loading"}),Fn().then(q=>p&&c({status:"ready",connection:q})).catch(()=>p&&c({status:"ready",connection:null})),()=>{p=!1}},[T,P,k]);const m=a.status==="ready"?a.connection:null,v=Zs(m?.environment),b=a.status==="ready"&&Je(m?.environment),x=a.status==="ready"&&(!b||Qs(u,s)),g=m?.environment;return $.useEffect(()=>{i(x,g)},[x,g,i]),n.jsxs("div",{className:l.root,children:[v&&n.jsx(se,{intent:"warning",children:n.jsxs(te,{children:[n.jsx(ke,{children:"Production environment"}),"This changes the live environment."]})}),n.jsxs("div",{className:l.box,children:[n.jsx(D,{className:l.label,children:"Environment"}),n.jsx("div",{className:l.value,children:a.status==="loading"?n.jsx(D,{children:"Reading the connection…"}):m?n.jsxs(n.Fragment,{children:[n.jsx(D,{weight:"semibold",children:m.name}),m.environment&&n.jsx(Ge,{size:"medium",appearance:v?"filled":"tint",color:v?"warning":"informative",children:m.environment}),n.jsx(D,{size:200,className:l.secondary,children:m.url})]}):n.jsx(D,{children:"Unknown (the tool has no connection)"})}),e.map(p=>n.jsxs("div",{style:{display:"contents"},children:[n.jsx(D,{className:l.label,children:p.label}),n.jsx("div",{className:l.value,children:p.value})]},p.label))]}),b&&n.jsx(Ne,{label:n.jsxs(n.Fragment,{children:["Type ",n.jsx("strong",{children:s})," to confirm"]}),hint:"Required on a Production environment.",children:n.jsx(Bn,{value:u,onChange:(p,q)=>y(q.value),disabled:o,autoComplete:"off","aria-label":`Type ${s} to confirm`})})]})}const Qn=Vn({content:{display:"flex",flexDirection:"column",gap:I.spacingVerticalM},changes:{listStyleType:"none",margin:0,padding:0,display:"flex",flexDirection:"column",gap:I.spacingVerticalXS},change:{display:"flex",alignItems:"flex-start",gap:I.spacingHorizontalS},changeIcon:{flexShrink:0,fontSize:"16px",marginTop:"2px",color:I.colorNeutralForeground3},changeText:{flex:1,minWidth:0,overflowWrap:"anywhere"},badge:{flexShrink:0},list:{margin:`${I.spacingVerticalXS} 0 0`,paddingLeft:"20px"},options:{display:"flex",flexDirection:"column",gap:I.spacingVerticalS},timing:{color:I.colorNeutralForeground3},progressList:{display:"flex",flexDirection:"column",gap:I.spacingVerticalXS},progressRow:{display:"flex",alignItems:"center",gap:I.spacingHorizontalS},xmlHeader:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:I.spacingHorizontalS},xml:{height:"360px",border:`1px solid ${I.colorNeutralStroke2}`,borderRadius:I.borderRadiusMedium,overflow:"hidden"}}),St={pending:"Waiting",publishing:"Publishing…",success:"Done",error:"Failed"},$t={pending:"subtle",publishing:"informative",success:"success",error:"danger"},It={new:{text:"New",color:"success",icon:n.jsx(Is,{})},change:{text:"Change",color:"brand",icon:n.jsx($s,{})},move:{text:"Move",color:"informative",icon:n.jsx(Ss,{})},show:{text:"Show",color:"informative",icon:n.jsx(Rs,{})},hide:{text:"Hide",color:"warning",icon:n.jsx(vs,{})},delete:{text:"Delete",color:"danger",icon:n.jsx(js,{})}},Xn=({findings:e,showScope:s})=>{const i=Qn();return n.jsx("ul",{className:i.list,children:e.map((o,l)=>n.jsxs("li",{children:[s&&n.jsxs("strong",{children:[o.scope,": "]}),o.message]},l))})},de=(e,s,i=`${s}s`)=>`${e} ${e===1?s:i}`,kt=3e4,Mt=()=>{const e=Qn(),s=Pn(t=>t.bulkPublishOpen),i=Pn(t=>t.closeBulkPublish),o=X(t=>t.ribbons),l=X(t=>t.baseline),a=X(t=>t.commands),c=X(t=>t.displayRules),u=X(t=>t.enableRules),y=X(t=>t.baselineCommands),T=X(t=>t.baselineEnableRules),P=X(t=>t.baselineDisplayRules),k=X(t=>t.locLabels),m=X(t=>t.baseLanguageCode),v=X(t=>t.baseLanguageUnknown),b=X(t=>t.setLayerSnapshot),x=X(t=>t.markPublished),g=W(t=>t.activeSolution),p=W(t=>t.activeEntity),q=W(t=>t.connectionUrl),G=W(t=>t.publisherPrefix),Y=W(t=>t.solutionRibbonComponentIds),{entityPlan:U,appPlan:V,solutionSupportsAppRibbon:J,includeApplicationRibbon:C,scopes:d,unsupported:N,warnings:A,changes:r}=et(),[h,j]=$.useState(!1),[R,S]=$.useState({}),[F,Z]=$.useState(!1),[_,es]=$.useState(!1),[ue,Te]=$.useState("targeted"),[sn,be]=$.useState(!1),Ae=ue==="allAsync"&&!sn,Ee=W(t=>t.connectionName||t.connectionUrl||"this environment"),[tn,De]=$.useState({confirmed:!1}),ns=re.useCallback((t,f)=>De({confirmed:t,environment:f}),[]),on=tn.confirmed,[ss,an]=$.useState(0),[ln,ie]=$.useState(""),[Le,rn]=$.useState(""),[ge,cn]=$.useState(g?.version??"1.0.0.0"),[ze,fe]=$.useState([]),[dn,un]=$.useState([]),[ts,is]=$.useState(0),[os,ye]=$.useState([]),[xe,Me]=$.useState("summary"),[as,Oe]=$.useState([]),hn=re.useMemo(()=>{const f=(ge||g?.version||"1.0.0.0").split(".").map(L=>Number.parseInt(L,10)||0);for(;f.length<4;)f.push(0);return f[3]+=1,f.slice(0,4).join(".")},[g?.version,ge]);re.useEffect(()=>{cn(g?.version??"1.0.0.0")},[g?.version]);const ls=p&&U?.hasChanges?p.logicalName:"application ribbon",[oe,we]=$.useState("idle"),[Ue,Xe]=$.useState([]),[mn,Be]=$.useState([]),[pn,Ve]=$.useState(""),H=s&&!!g&&N.length===0&&d.length>0,bn=g?.id,gn=g?.publisherPrefix||G,fn=re.useCallback(async()=>{const t={commands:a,enableRules:u,displayRules:c,locLabels:k,baselineCommands:y,baselineEnableRules:T,baselineDisplayRules:P,publisherPrefix:gn,languageCode:m},f={lookupWebResources:z=>tt(z,bn)},L=[],le=[];if(p&&U?.hasChanges){const z=await Mn({...t,entity:{logicalName:p.logicalName,schemaName:p.schemaName},locations:Ie.map(M=>({current:o[M],baseline:l[M]})),plan:U},f);L.push(...z.findings.map(M=>({...M,scope:p.logicalName}))),le.push({scope:p.logicalName,xml:z.xml})}if(C){const z=await Mn({...t,entity:null,locations:[{current:o.Application,baseline:l.Application}],plan:V},f);L.push(...z.findings.map(M=>({...M,scope:"Application ribbon"}))),le.push({scope:"Application ribbon",xml:z.xml})}return{findings:L,xml:le}},[p,U,V,C,o,l,a,u,c,k,y,T,P,gn,bn,m]);re.useEffect(()=>{if(!H||h||F)return;let t=!1;return we("running"),Ve(""),ut(fn(),kt).then(({findings:f,xml:L})=>{t||(Xe(f),Be(L),we("done"))}).catch(f=>{t||(Xe([]),Be([]),Ve(f instanceof Error?f.message:String(f)),we("failed"))}),()=>{t=!0}},[H,h,F,fn]);const Q=Ue.filter(t=>t.severity==="error"),yn=Ue.filter(t=>t.severity==="warning"),xn=new Set(Ue.map(t=>t.scope)).size>1,wn=H&&(oe==="running"||Q.length>0),rs=()=>nn(async()=>{if(!g||N.length>0||d.length===0||wn||!on||v||Ae)return;j(!0);const t=en(),f=W.getState().connectionVersion,L=()=>W.getState().connectionVersion!==f,le=await Fn().catch(()=>null);if(L()){j(!1);return}if(Je(le?.environment)&&!Je(tn.environment)){De({confirmed:!1}),an(w=>w+1),j(!1),Pe.getState().logWarn("publish",`${le?.name??"The connection"} is a Production environment now: type the confirmation to publish.`);return}ie(""),fe([]),ye([]),un(d),is(r.length),S(Object.fromEntries(d.map(w=>[w,"pending"])));let z=!1;const M=[],We={},ne=[],je=[],Fe=Pe.getState(),me=w=>w instanceof Error?w.message:String(w);Le.trim()&&Fe.logInfo("publish",`Publish comment: ${Le.trim()}`);const Rn={commands:a,enableRules:u,displayRules:c,locLabels:k,baselineCommands:y,baselineEnableRules:T,baselineDisplayRules:P,publishCustomizations:!0,languageCode:m,solution:{uniqueName:g.uniqueName,friendlyName:g.friendlyName,version:_?hn:ge,publisherUniqueName:g.publisherUniqueName,publisherName:g.publisherName,publisherPrefix:g.publisherPrefix||G,publisherOptionValuePrefix:g.publisherOptionValuePrefix}};if(p&&U?.hasChanges){const w=p.logicalName;S(E=>({...E,[w]:"publishing"}));try{const E=await On({...Rn,guard:t,entity:{logicalName:p.logicalName,schemaName:p.schemaName,displayName:p.displayName},locations:Ie.map(O=>({current:o[O],baseline:l[O]})),plan:U},O=>ie(O));M.push(...Ie),We.entity=E.parts,it(q,p.logicalName,E.changedKeys),E.verification&&je.push({scope:w,result:E.verification}),S(O=>({...O,[w]:"success"}))}catch(E){z=!0,ne.push({scope:w,message:me(E)}),Fe.logError("publish",`Ribbon publish failed (${w}): ${me(E)}`),S(O=>({...O,[w]:"error"}))}}else p&&M.push(...Ie);if(C&&!L()){const w="Application ribbon";S(E=>({...E,[w]:"publishing"}));try{const E=await On({...Rn,guard:t,entity:null,locations:[{current:o.Application,baseline:l.Application}],ribbonCustomizationIds:Y??[],plan:V},O=>ie(O));M.push("Application"),We.application=E.parts,E.verification&&je.push({scope:w,result:E.verification}),S(O=>({...O,[w]:"success"}))}catch(E){z=!0,ne.push({scope:w,message:me(E)}),Fe.logError("publish",`Application ribbon publish failed: ${me(E)}`),S(O=>({...O,[w]:"error"}))}}else V.hasChanges||M.push("Application");if(!z&&ue==="allAsync")try{await ft(w=>ie(w),{guard:t})}catch(w){z=!0,ne.push({scope:"Publish all customizations",message:me(w)})}if(L()){C&&!ne.some(w=>w.scope==="Application ribbon")&&ne.push({scope:"Application ribbon",message:"Not published: the tool's connection changed during the publish."}),ye(je),fe(ne),Z(!1),j(!1);return}if(x(M,We),p&&M.includes("HomepageGrid")&&U?.hasChanges){const w=await Tn(p.logicalName);w&&b("entity",w)}if(M.includes("Application")&&C){const w=await Tn(null);w&&b("application",w)}z||ie("Done."),ye(je),fe(ne),Z(!z),j(!1)}),Cn=()=>{j(!1),S({}),un([]),Z(!1),ie(""),fe([]),ye([]),we("idle"),Xe([]),Be([]),Ve(""),Me("summary"),Oe([]),De({confirmed:!1}),Te("targeted"),be(!1),rn(""),an(t=>t+1),i()},qe=V.hasChanges&&!J,Ce=N.length+(H?Q.length:0),jn=H?yn.length+(oe==="failed"?1:0):0;re.useEffect(()=>{Ce>0&&Oe(t=>t.includes("problems")?t:["problems",...t])},[Ce]);const ae=g?v?{intent:"error",title:"Reload the table first",text:"The organization's base language couldn't be read when the table loaded, so labels are shown in English. Publishing now could write English texts as the base language's titles."}:N.length>0?{intent:"error",title:`${de(N.length,"change")} can't be published yet`,text:`Undo ${N.length===1?"it":"them"} to publish the rest. Problems below says what each one is.`}:H&&Q.length>0?{intent:"error",title:`The check found ${de(Q.length,"problem")}`,text:`In what this publish would import. Fix ${Q.length===1?"it":"them"}, then open Publish again; Problems below lists ${Q.length===1?"it":"them"}.`}:d.length===0?qe?{intent:"warning",title:"The application ribbon can't be published from this solution",text:n.jsxs(n.Fragment,{children:["It doesn't include the Application Ribbons component. In make.powerapps.com open the solution, choose"," ",n.jsx("strong",{children:"Add existing → Application Ribbons"}),", then reload here."]})}:{intent:"info",title:"Nothing to publish",text:"Every change on this table is already published."}:Ae?{intent:"warning",title:"Confirm publishing everything",text:`Tick the confirmation under Options to publish every unpublished customization in ${Ee}.`,action:n.jsx(ce,{size:"small",onClick:()=>{Te("targeted"),be(!1)},children:"Only these ribbons"})}:null:{intent:"warning",title:"Choose a solution",text:"Publishing imports into a solution: choose one in the top bar first."},he=p?.displayName||p?.logicalName,vn=!!p&&!!U?.hasChanges,cs=vn&&C?`Publish ${he} and the application ribbon`:!vn&&C?"Publish the application ribbon":he?`Publish ${he}`:"Publish",ds=h?"Publishing…":r.length>0?`Publish ${de(r.length,"change")}`:"Publish",ee=!h&&!F;return n.jsx(nt,{open:s,onOpenChange:t=>!t&&!h&&Cn(),size:xe==="xml"?"large":"medium",title:xe==="xml"?"What Publish imports":cs,startActions:ee?xe==="summary"?n.jsx(ce,{appearance:"subtle",icon:n.jsx(ws,{}),onClick:()=>Me("xml"),children:"View XML"}):n.jsx(ce,{appearance:"subtle",icon:n.jsx(Cs,{}),onClick:()=>Me("summary"),children:"Back to summary"}):void 0,actions:n.jsxs(n.Fragment,{children:[n.jsx(ce,{appearance:"secondary",onClick:Cn,disabled:h,children:F?"Close":"Cancel"}),!F&&n.jsx(ce,{appearance:"primary",onClick:()=>{rs()},disabled:h||!g||d.length===0||N.length>0||wn||!on||v||Ae,children:ds})]}),children:xe==="xml"&&ee?n.jsxs("div",{className:e.content,children:[n.jsx(D,{children:"The complete RibbonDiffXml each import writes: your solution's layer as it is now, with your changes merged in."}),H&&oe==="running"?n.jsx(Sn,{size:"tiny",labelPosition:"after",label:"Building the XML…"}):mn.length===0?n.jsx(se,{intent:"info",layout:"multiline",children:n.jsx(te,{children:H&&oe==="failed"?`The XML couldn't be built: ${pn}`:"The XML is built once there is something to publish and nothing blocks it."})}):mn.map(t=>n.jsxs("div",{className:e.options,children:[n.jsxs("div",{className:e.xmlHeader,children:[n.jsx(D,{weight:"semibold",children:t.scope}),n.jsx(ce,{size:"small",appearance:"subtle",icon:n.jsx(us,{}),onClick:()=>{st(t.xml)},children:"Copy"})]}),n.jsx("div",{className:e.xml,children:n.jsx(ot,{language:"xml",value:t.xml,readOnly:!0})})]},t.scope))]}):n.jsxs("div",{className:e.content,children:[ee&&ae&&n.jsxs(se,{intent:ae.intent,layout:"multiline",children:[n.jsxs(te,{children:[n.jsx(ke,{children:ae.title}),ae.text]}),ae.action&&n.jsx(hs,{children:ae.action})]}),ee&&r.length>0&&n.jsxs("div",{className:e.options,children:[n.jsxs(D,{weight:"semibold",children:[de(r.length,"change")," to publish"]}),n.jsx("ul",{className:e.changes,"aria-label":"Changes to publish",children:r.map((t,f)=>{const L=It[t.kind];return n.jsxs("li",{className:e.change,children:[n.jsx("span",{className:e.changeIcon,"aria-hidden":"true",children:L.icon}),n.jsxs(D,{className:e.changeText,children:[t.action," ",n.jsx("strong",{children:t.name}),t.detail?` ${t.detail}`:""]}),n.jsx(Ge,{appearance:"tint",color:L.color,size:"medium",className:e.badge,children:L.text})]},f)})})]}),ee&&H&&oe==="running"&&n.jsx(Sn,{size:"tiny",labelPosition:"after",label:"Checking what this publish would import…"}),ee&&n.jsx(Rt,{rows:[{label:"Solution",value:g?n.jsx(D,{weight:"semibold",children:g.friendlyName||g.uniqueName}):n.jsx(D,{children:"None selected"})}],confirmWord:ls,onConfirmationChange:ns},ss),ee&&n.jsxs(ms,{multiple:!0,collapsible:!0,openItems:as,onToggle:(t,f)=>Oe(f.openItems),children:[Ce>0&&n.jsxs(ve,{value:"problems",children:[n.jsxs(Re,{children:["Problems · ",Ce]}),n.jsxs(Se,{children:[N.length>0&&n.jsxs(n.Fragment,{children:[n.jsx(D,{block:!0,children:"These changes can't be published yet; undo them:"}),n.jsx("ul",{className:e.list,children:N.map(t=>n.jsx("li",{children:t},t))})]}),H&&Q.length>0&&n.jsx(Xn,{findings:Q,showScope:xn})]})]}),jn>0&&n.jsxs(ve,{value:"warnings",children:[n.jsxs(Re,{children:["Warnings · ",jn]}),n.jsxs(Se,{children:[n.jsx(D,{block:!0,children:"You can still publish."}),oe==="failed"&&n.jsxs(D,{block:!0,children:["The check before publishing couldn't complete (",pn,"). Publishing runs it again before anything is imported."]}),n.jsx(Xn,{findings:yn,showScope:xn})]})]}),n.jsxs(ve,{value:"info",children:[n.jsxs(Re,{children:["Good to know ·"," ",A.length+1+(qe&&d.length>0?1:0)]}),n.jsx(Se,{children:n.jsxs("ul",{className:e.list,children:[n.jsx("li",{children:"Publishing writes this table's complete ribbon customization: what is already published, plus your changes. Ribbon changes imported elsewhere but not published are published first, so they are kept. Each ribbon is imported twice so Unified Interface picks up the change."}),qe&&d.length>0&&n.jsxs("li",{children:["Your application ribbon changes stay pending: this solution doesn't include the Application Ribbons component. In make.powerapps.com open the solution, choose"," ",n.jsx("strong",{children:"Add existing → Application Ribbons"}),", then reload here."]}),A.map(t=>n.jsx("li",{children:t},t))]})})]}),n.jsxs(ve,{value:"options",children:[n.jsx(Re,{children:"Options"}),n.jsxs(Se,{className:e.options,children:[n.jsx(Ne,{label:"Also publish",children:n.jsxs(ps,{value:ue==="targeted"?"Only these ribbons":"Every unpublished customization",selectedOptions:[ue],onOptionSelect:(t,f)=>{(f.optionValue==="targeted"||f.optionValue==="allAsync")&&(Te(f.optionValue),be(!1))},children:[n.jsx($n,{value:"targeted",children:"Only these ribbons"}),n.jsx($n,{value:"allAsync",children:"Every unpublished customization"})]})}),ue==="allAsync"&&n.jsx(se,{intent:"warning",layout:"multiline",children:n.jsxs(te,{children:[n.jsxs(D,{block:!0,children:["This publishes ",n.jsx("strong",{children:"every"})," ","unpublished customization in"," ",n.jsx("strong",{children:Ee}),", not only these ribbons: forms, views, tables and other people's work in progress included."]}),n.jsx(bs,{checked:sn,onChange:(t,f)=>be(f.checked===!0),label:`Publish all unpublished customizations in ${Ee}`})]})}),n.jsx(gs,{label:"Increment solution version",checked:_,onChange:(t,f)=>es(f.checked===!0)}),n.jsx(Ne,{label:"Solution version",children:n.jsx(Bn,{value:_?hn:ge,onChange:(t,f)=>cn(f.value),disabled:_})}),n.jsx(Ne,{label:"Publish comment",hint:"Written to the Console log with this publish; it isn't stored in Dataverse.",children:n.jsx(fs,{resize:"vertical",value:Le,onChange:(t,f)=>rn(f.value)})})]})]})]}),ee&&d.length>0&&n.jsx(ys,{className:e.timing,children:"Publishing takes 1–4 minutes. Users may need to refresh to see the change."}),ze.length>0&&n.jsx(se,{intent:"error",layout:"multiline",children:n.jsxs(te,{children:[n.jsxs(ke,{children:["Publish failed (",de(ze.length,"error"),")"]}),n.jsx("ul",{className:e.list,children:ze.map((t,f)=>n.jsxs("li",{style:{fontFamily:I.fontFamilyMonospace},children:[n.jsxs("strong",{children:[t.scope,":"]})," ",t.message]},f))}),n.jsxs("div",{style:{marginTop:I.spacingVerticalS},children:["Full details are in the ",n.jsx("strong",{children:"Console"})," tab of the bottom panel."]})]})}),F&&n.jsx(se,{intent:"success",layout:"multiline",children:n.jsxs(te,{children:[n.jsxs(ke,{children:["Published ",de(ts,"change"),he&&dn.includes(p?.logicalName??"")?` to ${he}`:""]}),"Unified Interface can take up to about 25 minutes to show it. To see it sooner, run ",n.jsx("strong",{children:"Regenerate ribbon metadata"})," in Command Checker, or hard-refresh the page (Ctrl+F5)."]})}),os.map(t=>n.jsx(se,{intent:t.result.ok?"success":"warning",layout:"multiline",children:n.jsxs(te,{children:[n.jsxs("strong",{children:[t.scope,":"]})," ",t.result.message]})},t.scope)),(h||F)&&n.jsxs("div",{className:e.progressList,children:[dn.map(t=>{const f=R[t]??"pending";return n.jsxs("div",{className:e.progressRow,children:[n.jsx(Ge,{appearance:"filled",color:$t[f],size:"medium",className:e.badge,children:St[f]}),n.jsx(D,{children:t}),f==="publishing"&&n.jsx(xs,{thickness:"large",style:{flex:1}})]},t)}),ln&&!F&&n.jsx(D,{className:e.timing,children:ln})]})]})})};export{Mt as BulkPublishModal,Mt as default};
@@ -0,0 +1 @@
1
+ import{r as I,j as s,m as ce,c as v,M as Q,K as q,k as b,at as U,Q as Y,R as Z,X as E,dX as X,e9 as ue,F as C,as as J,I as me,dB as pe,dC as be,cD as he,cB as xe,T as ge,aq as fe,ar as F,e7 as K,N as je,ai as we,dO as ye,a6 as Ce,a7 as ve,t as r}from"./fluent-ui-CQyNN9H3.js";import{D as Re,c as Ne,S as Se,v as ke,f as De,C as Ae,g as Te}from"./dnd-iy5K5XAJ.js";import{b as j,a as x,ak as Ie,aG as Ee,u as Be,c as Me,aH as $e,aI as _e,an as We,aD as Fe,aJ as Oe}from"./index-DRTwBo4g.js";import{C as G}from"./CrmParameterEditor-DO6Rt764.js";import{u as Pe}from"./useStableKeys-49o4VnxU.js";import"./preload-helper-PPVm8Dsz.js";import"./crmParameters-rgfZhhzN.js";const ee=ce({body:{display:"flex",flexDirection:"column",gap:r.spacingVerticalM},actionCard:{border:`1px solid ${r.colorNeutralStroke2}`,borderRadius:r.borderRadiusMedium,backgroundColor:r.colorNeutralBackground1,padding:r.spacingVerticalM,display:"flex",flexDirection:"column",gap:r.spacingVerticalS},actionHeader:{display:"flex",alignItems:"center",gap:r.spacingHorizontalXS,minWidth:0},actionTitle:{flex:1,minWidth:0},dragHandle:{cursor:"grab",touchAction:"none"},row:{display:"flex",flexWrap:"wrap",gap:r.spacingHorizontalS,alignItems:"flex-end"},library:{display:"flex",gap:r.spacingHorizontalXS,alignItems:"center"},grow:{flex:1,minWidth:0},ruleTags:{flexWrap:"wrap"},muted:{color:r.colorNeutralForeground3},usesList:{listStyleType:"none",margin:0,padding:0,display:"flex",flexDirection:"column",gap:r.spacingVerticalXS},use:{border:`1px solid ${r.colorNeutralStroke2}`,borderRadius:r.borderRadiusMedium,padding:`${r.spacingVerticalXS} ${r.spacingHorizontalS}`,display:"flex",flexDirection:"column",minWidth:0},fields:{border:"none",margin:0,padding:0,minWidth:0,display:"flex",flexDirection:"column",gap:r.spacingVerticalS,"&:disabled .fui-Input, &:disabled .fui-Select__select, &:disabled .fui-Dropdown, &:disabled .fui-Combobox":{backgroundColor:r.colorNeutralBackground3,borderTopColor:r.colorTransparentStroke,borderRightColor:r.colorTransparentStroke,borderBottomColor:r.colorTransparentStroke,borderLeftColor:r.colorTransparentStroke,color:r.colorNeutralForeground1,cursor:"default"},"&:disabled .fui-Input::after, &:disabled .fui-Dropdown::after, &:disabled .fui-Combobox::after":{display:"none"},"&:disabled input, &:disabled .fui-Dropdown__button":{color:r.colorNeutralForeground1,cursor:"default"},"&:disabled .fui-Select__icon, &:disabled .fui-Dropdown__expandIcon, &:disabled .fui-Combobox__expandIcon":{display:"none"},"&:disabled .fui-Button":{color:r.colorNeutralForegroundDisabled,borderTopColor:r.colorNeutralStrokeDisabled,borderRightColor:r.colorNeutralStrokeDisabled,borderBottomColor:r.colorNeutralStrokeDisabled,borderLeftColor:r.colorNeutralStrokeDisabled,cursor:"not-allowed"}}}),Le=[],ze=n=>{const d=n.trim();return d.startsWith("$webresource:")?d.slice(13).trim():d};function Ve(n){switch(n.kind){case"javascript":return"Run JavaScript";case"url":return"Open a URL";case"powerFx":return"Power Fx (not supported)";case"customApi":return"Custom API (not supported)";case"outlookCommand":return"Outlook command";case"raw":return n.tagName;default:return"Action"}}function He({id:n,index:d,count:u,title:R,readOnly:g,onMove:N,onRemove:B,children:w}){const y=ee(),{attributes:M,listeners:D,setNodeRef:S,setActivatorNodeRef:A,transform:T,transition:$}=De({id:n,disabled:g});return s.jsxs("section",{ref:S,style:{transform:Ae.Transform.toString(T),transition:$},className:y.actionCard,"aria-label":`Action ${d+1}: ${R}`,children:[s.jsxs("div",{className:y.actionHeader,children:[!g&&u>1&&s.jsx(b,{ref:A,appearance:"subtle",size:"small",className:y.dragHandle,icon:s.jsx(pe,{}),"aria-label":"Drag to reorder action",...M,...D}),s.jsx(v,{weight:"semibold",className:y.actionTitle,truncate:!0,wrap:!1,children:R}),!g&&u>1&&s.jsxs(Q,{children:[s.jsx(q,{disableButtonEnhancement:!0,children:s.jsx(b,{appearance:"subtle",size:"small",icon:s.jsx(be,{}),"aria-label":"More for this action"})}),s.jsx(Y,{children:s.jsxs(Z,{children:[s.jsx(E,{icon:s.jsx(he,{}),disabled:d===0,onClick:()=>N(d,d-1),children:"Move up"}),s.jsx(E,{icon:s.jsx(xe,{}),disabled:d===u-1,onClick:()=>N(d,d+1),children:"Move down"})]})})]}),!g&&s.jsx(ge,{content:"Remove action",relationship:"label",children:s.jsx(b,{appearance:"subtle",size:"small",icon:s.jsx(fe,{}),onClick:B})})]}),w]})}const Ye=()=>{const n=ee(),d=j(e=>e.commandEditorOpen),u=j(e=>e.commandEditorId),R=j(e=>e.closeCommandEditor),g=j(e=>e.openRuleEditor),N=j(e=>e.openScriptView),B=j(e=>e.openWebResourceBrowser),w=j(e=>e.commandEditorTab),y=x(e=>e.commands),M=x(e=>e.upsertCommand),D=x(e=>e.ribbons),S=x(e=>e.locLabels),A=x(e=>e.displayRules),T=x(e=>e.enableRules),$=x(e=>e.upsertEnableRule),se=x(e=>e.upsertDisplayRule),_=Ie(),[ae,O]=I.useState(""),[re,P]=I.useState(""),l=y.find(e=>e.id===u),m=Pe(`actions:${l?.id??""}`,l?.actions??Le),f=Ee(Be(l?.id));I.useEffect(()=>{d&&u&&!l&&R()},[d,u,l,R]);const L=I.useMemo(()=>u?Me(D,u):[],[D,u]);if(!l)return null;const k=e=>{M({...l,...e})},h=(e,a)=>{const t=[...l.actions];t[e]=a,k({actions:t}),m.update()},ne=e=>{k({actions:l.actions.filter((a,t)=>t!==e)}),m.remove(e)},z=(e,a)=>{a<0||a>=l.actions.length||e===a||(k({actions:Te(l.actions,e,a)}),m.move(e,a))},oe=e=>{e.over&&z(m.keys.indexOf(String(e.active.id)),m.keys.indexOf(String(e.over.id)))},V=e=>{const a=e==="javascript"?{kind:"javascript",library:"",functionName:"",params:[]}:{kind:"url",address:"https://",params:[]};k({actions:[...l.actions,a]}),m.add()},le=(e,a)=>{if(e.kind==="javascript"){const t=ze(e.library);return s.jsxs(s.Fragment,{children:[s.jsxs("fieldset",{disabled:f,className:n.fields,children:[s.jsx(C,{label:"Library",hint:"A JavaScript web resource, like $webresource:publisher_/scripts/file.js.",children:s.jsxs("div",{className:n.library,children:[s.jsx(F,{className:n.grow,value:e.library,onChange:(o,c)=>h(a,{...e,library:c.value.replace(/^(\s*\$webresource:\s*)+/i,"$webresource:")}),placeholder:"$webresource:publisher_/scripts/file.js"}),s.jsx(b,{onClick:()=>{Fe.set(o=>{h(a,{...e,library:`$webresource:${o.name}`})}),B()},children:"Browse…"})]})}),s.jsx(C,{label:"Function",hint:"The function's full name, including its namespace.",children:s.jsx(F,{value:e.functionName,onChange:(o,c)=>h(a,{...e,functionName:c.value}),placeholder:"Contoso.Account.approve"})}),s.jsx(K,{weight:"semibold",children:"Parameters, in order"}),s.jsx(G,{params:e.params,onChange:o=>h(a,{...e,params:o}),urlMode:!1})]}),s.jsxs("div",{className:n.row,children:[s.jsx(b,{size:"small",icon:s.jsx(je,{}),disabled:!t,onClick:()=>N(t,!1),children:"View script"}),!f&&s.jsx(b,{size:"small",icon:s.jsx(we,{}),disabled:!t,onClick:()=>N(t,!0),children:"Edit script"})]})]})}if(e.kind==="url"){const t=e.address.trim().startsWith("https://");return s.jsxs("fieldset",{disabled:f,className:n.fields,children:[s.jsx(C,{label:"Address",validationState:t?"none":"error",validationMessage:t?void 0:"The address must start with https://",children:s.jsx(F,{value:e.address,onChange:(o,c)=>h(a,{...e,address:c.value}),placeholder:"https://"})}),s.jsx(C,{label:"Open in",children:s.jsxs(J,{value:String(e.winMode??0),onChange:(o,c)=>h(a,{...e,winMode:parseInt(c.value)}),children:[s.jsx("option",{value:"0",children:"Navigate (0)"}),s.jsx("option",{value:"1",children:"Dialog (1)"}),s.jsx("option",{value:"2",children:"Popup (2)"})]})}),s.jsx(C,{hint:"Adds the record's details to the address: typename, type, id, orgname and the user's languages.",children:s.jsx(ye,{label:"Pass parameters",checked:!!e.passParams,onChange:(o,c)=>h(a,{...e,passParams:c.checked?!0:void 0})})}),s.jsx(K,{weight:"semibold",children:"Query string parameters"}),s.jsx(G,{params:e.params,onChange:o=>h(a,{...e,params:o}),urlMode:!0})]})}return e.kind==="powerFx"||e.kind==="customApi"?s.jsx(Ce,{intent:"error",children:s.jsxs(ve,{children:["Classic ribbon commands can't run"," ",e.kind==="powerFx"?"Power Fx":"Custom API"," actions, so this command can't be published while it has one. Remove it and use a JavaScript function instead (for example, call the API with"," ",s.jsx("code",{children:"Xrm.WebApi.online.execute"}),"), or build the command with modern commanding in the app designer."]})}):e.kind==="outlookCommand"||e.kind==="raw"?s.jsx(v,{size:200,className:n.muted,children:e.kind==="outlookCommand"?`ActionType="${e.actionType}"${e.data?` Data="${e.data}"`:""}`:e.xml}):null},te=()=>s.jsxs(s.Fragment,{children:[s.jsx(Re,{collisionDetection:Ne,onDragEnd:oe,children:s.jsx(Se,{items:m.keys,strategy:ke,children:l.actions.map((e,a)=>s.jsx(He,{id:m.keys[a],index:a,count:l.actions.length,title:Ve(e),readOnly:f,onMove:z,onRemove:()=>ne(a),children:le(e,a)},m.keys[a]))})}),l.actions.length===0&&s.jsx(v,{className:n.muted,children:"No actions yet. The button does nothing when it's clicked."}),!f&&s.jsx("div",{children:s.jsxs(Q,{children:[s.jsx(q,{disableButtonEnhancement:!0,children:s.jsx(b,{icon:s.jsx(U,{}),children:"Add action"})}),s.jsx(Y,{children:s.jsxs(Z,{children:[s.jsx(E,{onClick:()=>V("javascript"),children:"Run JavaScript"}),s.jsx(E,{onClick:()=>V("url"),children:"Open a URL"})]})})]})}),s.jsx(X,{className:n.muted,children:"Every user's browser gets the command's definition, even when the button is hidden. Don't put secrets in function names or parameters."})]}),H=e=>{const a=e==="enable"?l.enableRules:l.displayRules,t=(e==="enable"?T:A).map(i=>i.id).filter(i=>!a.includes(i)),o=e==="enable"?ae:re,c=i=>k(e==="enable"?{enableRules:i}:{displayRules:i}),de=()=>{const i=new Set([...T.map(W=>W.id),...A.map(W=>W.id)]),p=Oe("New",e==="enable"?"Enable":"Display",i);e==="enable"?$({id:p,steps:[]}):se({id:p,steps:[]}),c([...a,p]),g(p,e)};return s.jsxs(s.Fragment,{children:[a.length>0?s.jsx(ue,{className:n.ruleTags,"aria-label":e==="enable"?"Enable rules":"Display rules",children:a.map(i=>s.jsx(_e,{ruleId:i,kind:e,onOpen:()=>g(i,e),onRemove:f?void 0:()=>c(a.filter(p=>p!==i))},i))}):s.jsxs(v,{className:n.muted,children:["No ",e," rules, so the button is always"," ",e==="enable"?"enabled":"shown","."]}),!f&&s.jsxs("div",{className:n.row,children:[s.jsx(C,{label:`Add an existing ${e} rule`,style:{flex:"1 1 260px",minWidth:0},children:s.jsxs(J,{style:{width:"100%",maxWidth:"100%",minWidth:0},value:o,onChange:(i,p)=>e==="enable"?O(p.value):P(p.value),children:[s.jsx("option",{value:"",children:"Select a rule…"}),t.map(i=>s.jsx("option",{value:i,children:i},i))]})}),s.jsx(b,{disabled:!o,onClick:()=>{o&&(c([...a,o]),e==="enable"?O(""):P(""))},children:"Add"}),s.jsxs(b,{appearance:"subtle",icon:s.jsx(U,{}),onClick:de,children:["New ",e," rule"]})]}),e==="enable"&&s.jsx(me,{size:"small",info:"Disabled buttons are hidden in the modern command bar (Unified Interface). In the classic ribbon, they stay visible but do nothing when clicked.",children:"What a failing enable rule does"})]})},ie=()=>L.length===0?s.jsx(v,{className:n.muted,children:"No button uses this command."}):s.jsx("ul",{className:n.usesList,"aria-label":"Buttons using this command",children:L.map(({location:e,tab:a,group:t,button:o})=>s.jsxs("li",{className:n.use,children:[s.jsx(v,{weight:"semibold",truncate:!0,wrap:!1,children:_(o.label,S,void 0,o.source?.labelToken)||o.id}),s.jsx(X,{className:n.muted,children:[We[e].label,_(a.label,S)||a.id,_(t.label,S)||t.id].join(" › ")})]},`${e}:${a.id}:${t.id}:${o.id}`))});return s.jsxs("div",{className:n.body,children:[s.jsx($e,{commandId:l.id,hideBadge:!0}),w==="actions"&&te(),w==="enable"&&H("enable"),w==="display"&&H("display"),w==="usedBy"&&ie()]})};export{Ye as CommandEditorPanel,Ye as default};
@@ -0,0 +1 @@
1
+ import{r as k,j as s,D as ie,f as re,dP as ce,dX as m,B as de,c as ne,e as ue,m as pe,t as n}from"./fluent-ui-CQyNN9H3.js";import{b as c,a as d,ak as me,S as he,al as be,a2 as S,am as fe,aa as ge,t as xe,an as ke}from"./index-DRTwBo4g.js";import"./preload-helper-PPVm8Dsz.js";import"./dnd-iy5K5XAJ.js";const we=pe({surface:{width:"calc(100vw - 32px)",maxWidth:"640px",padding:0,alignSelf:"flex-start",marginTop:"10vh",overflow:"hidden",display:"flex",flexDirection:"column",maxHeight:"calc(80vh)"},search:{padding:n.spacingVerticalM,borderBottom:`1px solid ${n.colorNeutralStroke2}`},searchBox:{width:"100%",maxWidth:"none"},results:{overflowY:"auto",padding:`${n.spacingVerticalXS} 0`,minHeight:0,flex:1},groupLabel:{display:"block",padding:`${n.spacingVerticalS} ${n.spacingHorizontalM} ${n.spacingVerticalXXS}`,color:n.colorNeutralForeground3,fontWeight:n.fontWeightSemibold},item:{display:"flex",alignItems:"center",gap:n.spacingHorizontalS,padding:`${n.spacingVerticalS} ${n.spacingHorizontalM}`,cursor:"pointer",minWidth:0},itemActive:{backgroundColor:n.colorNeutralBackground1Selected,boxShadow:`inset 2px 0 0 ${n.colorBrandStroke1}`},kind:{flexShrink:0,minWidth:"72px",justifyContent:"center"},itemText:{flex:1,minWidth:0,display:"flex",flexDirection:"column"},itemLabel:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},itemSub:{color:n.colorNeutralForeground3,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},more:{display:"block",padding:`${n.spacingVerticalXXS} ${n.spacingHorizontalM}`,color:n.colorNeutralForeground3},empty:{display:"block",padding:n.spacingVerticalL,textAlign:"center",color:n.colorNeutralForeground3},footer:{display:"flex",flexWrap:"wrap",gap:n.spacingHorizontalL,padding:`${n.spacingVerticalS} ${n.spacingHorizontalM}`,borderTop:`1px solid ${n.colorNeutralStroke2}`,color:n.colorNeutralForeground3}}),ye={action:"Action",button:"Button",command:"Command",enable:"Enable rule",display:"Display rule",table:"Table"},ve=[{kinds:["action"],title:"Actions",limit:1/0},{kinds:["button"],title:"Buttons",limit:20},{kinds:["command"],title:"Commands",limit:30},{kinds:["enable","display"],title:"Rules",limit:30},{kinds:["table"],title:"Tables",limit:30}],D=l=>`palette-${l.replace(/[^\w-]/g,"_")}`,je=()=>{const l=we(),C=c(e=>e.commandPaletteOpen),se=c(e=>e.setCommandPaletteOpen),R=c(e=>e.openBulkPublish),T=c(e=>e.openXmlDrawer),w=c(e=>e.openImportXml),E=c(e=>e.openCommandEditor),X=c(e=>e.openRuleEditor),O=c(e=>e.openNewGroup),A=c(e=>e.openNewButton),V=c(e=>e.openLocalizationEditor),W=d(e=>e.undo),z=d(e=>e.redo),H=d(e=>e.past.length>0),P=d(e=>e.future.length>0),F=d(e=>e.commands),G=d(e=>e.displayRules),U=d(e=>e.enableRules),j=d(e=>e.ribbons),N=d(e=>e.locLabels),$=me(),_=he(e=>e.entities),q=be(e=>e.requestEntitySwitch),I=S(e=>e.location),K=S(e=>e.tabId),Y=S(e=>e.selectedButtonId),L=S(e=>e.selectedGroupId),Q=S(e=>e.selectButtonInContext),[x,Z]=k.useState(""),[le,h]=k.useState(0),J=k.useRef(null),ee=()=>{se(!1),Z(""),h(0)},y=x.startsWith("/")?"actions":x.startsWith("@")?"tables":"all",M=(y==="all"?x:x.slice(1)).trim().toLowerCase(),te=k.useMemo(()=>{if(!C)return[];const e=[],t=j[I].tabs.find(o=>o.id===K),i=L??t?.groups[0]?.id??null,u=fe(t?.groups.find(o=>o.id===L),Y),p=(o,r,a,f)=>e.push({id:`act-${o}`,label:r,subtitle:a,kind:"action",run:f});p("publish","Publish…","Review and publish your changes",R),p("view-xml","View XML","The XML of your changes",()=>T(I)),p("import-xml","Import XML…","Import RibbonDiffXml from the clipboard",()=>{const o="Couldn't read the clipboard here: paste the XML into the editor (Ctrl+V).",r=navigator.clipboard?.readText?.();if(!r)return w("",o);r.then(a=>a.trim().startsWith("<")?w(a):w("","The clipboard doesn't hold XML: paste the XML into the editor."),()=>w("",o))}),t&&p("new-group","New group…","In the current tab",O),i&&p("new-button","New button…","In the selected or first group",()=>A(i)),u&&!ge(u.kind)&&(u.origin===void 0||u.origin==="unmanaged")&&p("translations","Translations…","The selected button's text",()=>V(u.id)),H&&p("undo","Undo","Ctrl+Z",W),P&&p("redo","Redo","Ctrl+Y",z);for(const[o,r]of Object.entries(j))for(const a of r.tabs)for(const f of a.groups)for(const g of xe(f))e.push({id:`btn-${o}-${g.id}`,label:$(g.label,N,void 0,g.source?.labelToken)||g.id,subtitle:[ke[o].label,$(a.label,N,void 0,a.source?.titleToken)||a.id,$(f.label,N,void 0,f.source?.titleToken)||f.id].join(" › "),keywords:`${g.label} ${g.id}`,kind:"button",run:()=>Q(o,a.id,f.id,g.id)});for(const o of F)e.push({id:`cmd-${o.id}`,label:o.id,subtitle:`${o.actions.length} action${o.actions.length===1?"":"s"}`,kind:"command",run:()=>E(o.id)});for(const[o,r]of[[U,"enable"],[G,"display"]])for(const a of o)e.push({id:`${r}-${a.id}`,label:a.id,subtitle:`${a.steps.length} step${a.steps.length===1?"":"s"}`,kind:r,run:()=>X(a.id,r)});for(const o of _)e.push({id:`ent-${o.logicalName}`,label:o.displayName,subtitle:o.logicalName,kind:"table",run:()=>q(o)});return e},[C,j,I,K,L,Y,H,P,F,U,G,_,N,$,R,T,w,O,A,V,E,X,W,z,Q,q]),B=k.useMemo(()=>{const e=t=>!M||[t.label,t.subtitle??"",t.keywords??""].some(i=>i.toLowerCase().includes(M));return ve.filter(t=>y==="all"||y==="actions"&&t.kinds.includes("action")||y==="tables"&&t.kinds.includes("table")).map(t=>{const i=te.filter(u=>t.kinds.includes(u.kind)&&e(u));return{...t,shown:i.slice(0,t.limit),more:Math.max(0,i.length-t.limit)}}).filter(t=>t.shown.length>0)},[te,M,y]),v=B.flatMap(e=>e.shown),b=v[Math.min(le,v.length-1)];k.useEffect(()=>{b&&J.current?.querySelector(`#${D(b.id)}`)?.scrollIntoView?.({block:"nearest"})},[b]);const oe=e=>{e&&(ee(),e.run())},ae=e=>{e.key==="ArrowDown"?(e.preventDefault(),h(t=>Math.min(t+1,v.length-1))):e.key==="ArrowUp"?(e.preventDefault(),h(t=>Math.max(t-1,0))):e.key==="Home"?(e.preventDefault(),h(0)):e.key==="End"?(e.preventDefault(),h(v.length-1)):e.key==="Enter"&&(e.preventDefault(),oe(b))};return s.jsx(ie,{open:C,onOpenChange:(e,t)=>!t.open&&ee(),children:s.jsxs(re,{className:l.surface,"aria-label":"Command palette",children:[s.jsx("div",{className:l.search,children:s.jsx(ce,{className:l.searchBox,size:"large",autoFocus:!0,placeholder:"Search buttons, commands, rules and tables",value:x,onChange:(e,t)=>{Z(t.value),h(0)},input:{role:"combobox","aria-label":"Search","aria-expanded":!0,"aria-controls":"palette-results","aria-activedescendant":b?D(b.id):void 0,"aria-autocomplete":"list",onKeyDown:ae}})}),s.jsxs("div",{ref:J,id:"palette-results",role:"listbox","aria-label":"Results",className:l.results,children:[B.map(e=>s.jsxs("div",{role:"group","aria-label":e.title,children:[s.jsx(m,{className:l.groupLabel,role:"presentation",children:e.title}),e.shown.map(t=>{const i=t===b;return s.jsxs("div",{id:D(t.id),role:"option","aria-selected":i,className:ue(l.item,i&&l.itemActive),onClick:()=>oe(t),onMouseMove:()=>h(v.indexOf(t)),children:[s.jsx(de,{className:l.kind,appearance:"tint",size:"medium",color:t.kind==="action"?"brand":"informative",children:ye[t.kind]}),s.jsxs("span",{className:l.itemText,children:[s.jsx(ne,{className:l.itemLabel,children:t.label}),t.subtitle&&s.jsx(m,{className:l.itemSub,children:t.subtitle})]})]},t.id)}),e.more>0&&s.jsxs(m,{className:l.more,role:"presentation",children:[e.more," more: keep typing to narrow it down."]})]},e.title)),B.length===0&&s.jsxs(ne,{className:l.empty,role:"presentation",children:["Nothing matches “",x,"”."]})]}),s.jsxs("div",{className:l.footer,"aria-hidden":"true",children:[s.jsx(m,{children:"↑ ↓ move"}),s.jsx(m,{children:"Enter choose"}),s.jsx(m,{children:"Esc close"}),s.jsx(m,{children:"/ actions only"}),s.jsx(m,{children:"@ tables only"})]})]})})};export{je as CommandPalette,je as default};
@@ -0,0 +1,7 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./monacoSetup-BIq1zGyP.js","./monaco-cQE5XS3B.js","./fluent-ui-CQyNN9H3.js","./preload-helper-PPVm8Dsz.js","./monaco-DQA8g3bM.css"])))=>i.map(i=>d[i]);
2
+ import{_ as E}from"./preload-helper-PPVm8Dsz.js";import{W as m,r as S,j as e,c as y,dv as P,t as l,k as z,dX as A,B as w,dZ as X,d_ as D,dY as $,m as F}from"./fluent-ui-CQyNN9H3.js";import{b as V,a as k,aO as C,d as W,aP as H}from"./index-DRTwBo4g.js";import"./dnd-iy5K5XAJ.js";const I=m.lazy(()=>E(()=>import("./monacoSetup-BIq1zGyP.js"),__vite__mapDeps([0,1,2,3,4]),import.meta.url).then(()=>E(()=>import("./monaco-cQE5XS3B.js").then(t=>t.i),__vite__mapDeps([1,2,3,4]),import.meta.url)).then(t=>({default:t.DiffEditor}))),U=["HomepageGrid","SubGrid","Form","Application"],G=F({root:{flex:1,display:"flex",flexDirection:"column",gap:l.spacingVerticalS,minHeight:"320px"},unchanged:{flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:l.spacingVerticalM,textAlign:"center",color:l.colorNeutralForeground3},bar:{display:"flex",alignItems:"center",flexWrap:"wrap",gap:l.spacingHorizontalS},spacer:{flex:1},muted:{color:l.colorNeutralForeground3},editor:{flex:1,minHeight:"240px",border:`1px solid ${l.colorNeutralStroke2}`,borderRadius:l.borderRadiusMedium,overflow:"hidden",position:"relative"},loading:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%"}});function q(t,n){const d=t.split(`
3
+ `),s=n.split(`
4
+ `);let i=0,c=0;const b=new Set(d),x=new Set(s);for(const h of s)b.has(h)||i++;for(const h of d)x.has(h)||c++;return{added:i,removed:c}}function j(t,n,d=!1){return U.map(s=>{const i=d?n[s]:t.ribbons[s];try{return`<!-- ${s} -->
5
+ `+W({location:s,current:i,baseline:n[s],commands:t.commands,displayRules:t.displayRules,enableRules:t.enableRules,locLabels:t.locLabels,entityLogicalName:i.entityLogicalName})}catch(c){return`<!-- ${s}: Error generating XML: ${String(c)} -->`}}).join(`
6
+
7
+ `)}const Q=({historyIndex:t})=>{const n=G(),d=V(a=>a.themeMode),s=t!==void 0,[i,c]=m.useState(!0),[b,x]=m.useState(!1),h=k(a=>!s&&a.mutationsSincePublish===0&&!H(a)),r=k(),o=s?r.past[t]:void 0,v=S.useMemo(()=>s?o?j(o.snapshot,r.baseline):"":j(r,r.baseline,!0),[s,o]),u=s?r.past[t+1]?.snapshot??C(r):C(r),L=S.useMemo(()=>s&&!o?"":j(u,r.baseline),[s,o,u.ribbons,u.commands,u.displayRules,u.enableRules,u.locLabels,r.baseline]),{added:M,removed:N}=q(v,L),R=m.useRef(null),O=m.useCallback(a=>{R.current=a,a.updateOptions({renderSideBySide:i});const p=[a.getOriginalEditor(),a.getModifiedEditor()];let g=0;const T=()=>{g||(g=requestAnimationFrame(()=>{g=0;for(const f of p)f.render(!0)}))},B=p.flatMap(f=>{const _=f.onDidChangeModelTokens;return _?[_.call(f,T)]:[]});a.onDidDispose(()=>{cancelAnimationFrame(g);for(const f of B)f.dispose()})},[]);return m.useEffect(()=>{R.current?.updateOptions({renderSideBySide:i})},[i]),s&&!o?e.jsx("div",{className:n.unchanged,children:e.jsx(y,{children:"This change was undone, so there's nothing to show."})}):!s&&!b&&h?e.jsxs("div",{className:n.unchanged,children:[e.jsx(P,{fontSize:40,color:l.colorPaletteGreenForeground1,"aria-hidden":"true"}),e.jsx(y,{size:500,weight:"semibold",children:"No changes since the last publish"}),e.jsx(y,{children:"What you see matches what's published for this table."}),e.jsx(z,{onClick:()=>x(!0),children:"Show the full XML anyway"})]}):e.jsxs("div",{className:n.root,children:[e.jsx(A,{className:n.muted,children:s?`${[o.op,o.target].filter(Boolean).join(" ")}${o.detail?` (${o.detail})`:""}: the XML before it (left) and after it (right).`:"The published XML (left) and the XML with your changes (right)."}),e.jsxs("div",{className:n.bar,children:[e.jsxs(w,{appearance:"tint",color:M?"success":"informative",children:["+",M," lines"]}),e.jsxs(w,{appearance:"tint",color:N?"danger":"informative",children:["-",N," lines"]}),e.jsx("div",{className:n.spacer}),e.jsxs(X,{size:"small",selectedValue:i?"side":"unified",onTabSelect:(a,p)=>c(p.value==="side"),"aria-label":"Diff layout",children:[e.jsx(D,{value:"side",children:"Side by side"}),e.jsx(D,{value:"unified",children:"Unified"})]})]}),e.jsx("div",{className:n.editor,children:e.jsx(S.Suspense,{fallback:e.jsx("div",{className:n.loading,children:e.jsx($,{size:"small",label:"Loading the diff…"})}),children:e.jsx(I,{original:v,modified:L,language:"xml",theme:d==="dark"?"vs-dark":"vs",height:"100%",onMount:O,options:{readOnly:!0,renderSideBySide:i,lineNumbers:"on",minimap:{enabled:!1},scrollBeyondLastLine:!1,automaticLayout:!0,wordWrap:"on"}})})})]})};export{Q as CompareView,Q as default};
@@ -0,0 +1 @@
1
+ import{j as e,F as h,as as P,ar as S,dO as j,T as p,k as v,cD as b,cB as f,l as y,at as I,m as k,W as g,t as u}from"./fluent-ui-CQyNN9H3.js";import{U as N}from"./crmParameters-rgfZhhzN.js";const R=k({root:{display:"flex",flexDirection:"column",gap:u.spacingVerticalXS,minWidth:0},param:{display:"flex",flexWrap:"wrap",minWidth:0,gap:u.spacingHorizontalS,alignItems:"flex-end",padding:u.spacingVerticalXS,border:`1px solid ${u.colorNeutralStroke2}`,borderRadius:u.borderRadiusMedium},typeSelect:{flex:"0 1 170px",minWidth:"130px"},nameField:{flex:"0 1 150px",minWidth:"110px"},valueField:{flex:"1 1 160px",minWidth:0,"& .fui-Select, & .fui-Input, & select":{width:"100%",minWidth:0}},actions:{display:"flex",gap:u.spacingHorizontalXS,flexShrink:0},addButton:{alignSelf:"flex-start"}}),A=[{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"]}];function F({value:r,integer:c,onChange:x}){const[i,s]=g.useState(String(r));return g.useEffect(()=>s(Number.isFinite(r)?String(r):""),[r]),e.jsx(S,{type:"number",value:i,onChange:(C,d)=>{s(d.value);const m=Number(d.value);d.value.trim()!==""&&Number.isFinite(m)&&(!c||Number.isInteger(m))&&!/e/i.test(String(m))&&x(m)},onBlur:()=>s(Number.isFinite(r)?String(r):"")})}const E=({params:r,onChange:c,urlMode:x=!1})=>{const i=R(),s=(l,t)=>{const a=[...r];a[l]=t,c(a)},C=l=>{c(r.filter((t,a)=>a!==l))},d=(l,t)=>{const a=[...r],n=l+t;n<0||n>=a.length||([a[l],a[n]]=[a[n],a[l]],c(a))},m=()=>{c([...r,{kind:"CrmParameter",value:"PrimaryControl"}])};return e.jsxs("div",{className:i.root,children:[r.map((l,t)=>e.jsxs("div",{className:i.param,children:[e.jsx(h,{label:"Type",size:"small",className:i.typeSelect,children:e.jsxs(P,{value:l.kind,onChange:(a,n)=>{const o=n.value;o==="CrmParameter"?s(t,{kind:o,value:"PrimaryControl"}):o==="BoolParameter"?s(t,{kind:o,value:!1}):o==="IntParameter"||o==="DecimalParameter"?s(t,{kind:o,value:0}):s(t,{kind:"StringParameter",value:""})},children:[e.jsx("option",{value:"CrmParameter",children:"From the context"}),e.jsx("option",{value:"StringParameter",children:"Text"}),e.jsx("option",{value:"BoolParameter",children:"True or false"}),e.jsx("option",{value:"IntParameter",children:"Whole number"}),e.jsx("option",{value:"DecimalParameter",children:"Decimal number"})]})}),x&&e.jsx(h,{label:"Name",size:"small",className:i.nameField,validationState:l.kind==="CrmParameter"&&!l.name?"error":"none",validationMessage:l.kind==="CrmParameter"&&!l.name?"Needs a name: it's the query string key.":void 0,children:e.jsx(S,{value:l.name??"",onChange:(a,n)=>s(t,{...l,name:n.value||void 0}),placeholder:"key"})}),e.jsx(h,{label:"Value",size:"small",className:i.valueField,children:l.kind==="CrmParameter"?e.jsx(P,{value:l.value,onChange:(a,n)=>s(t,{...l,value:n.value}),children:A.map(a=>e.jsx("optgroup",{label:a.label,children:a.values.filter(n=>!x||!N.has(n)).map(n=>e.jsx("option",{value:n,children:n},n))},a.label))}):l.kind==="BoolParameter"?e.jsx(j,{checked:l.value,onChange:(a,n)=>s(t,{...l,value:n.checked}),label:l.value?"True":"False"}):l.kind==="StringParameter"?e.jsx(S,{value:String(l.value),onChange:(a,n)=>s(t,{...l,value:n.value})}):e.jsx(F,{value:l.value,integer:l.kind==="IntParameter",onChange:a=>s(t,{...l,value:a})})}),e.jsxs("div",{className:i.actions,children:[e.jsx(p,{content:`Move parameter ${t+1} up`,relationship:"label",children:e.jsx(v,{appearance:"subtle",size:"small",icon:e.jsx(b,{}),onClick:()=>d(t,-1),disabled:t===0})}),e.jsx(p,{content:`Move parameter ${t+1} down`,relationship:"label",children:e.jsx(v,{appearance:"subtle",size:"small",icon:e.jsx(f,{}),onClick:()=>d(t,1),disabled:t===r.length-1})}),e.jsx(p,{content:`Remove parameter ${t+1}`,relationship:"label",children:e.jsx(v,{appearance:"subtle",size:"small",icon:e.jsx(y,{}),onClick:()=>C(t)})})]})]},t)),e.jsx(v,{className:i.addButton,appearance:"secondary",size:"small",icon:e.jsx(I,{}),onClick:m,children:"Add parameter"})]})};export{E as C};
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./CommandEditorPanel-DYsxUTOk.js","./fluent-ui-CQyNN9H3.js","./dnd-iy5K5XAJ.js","./index-DRTwBo4g.js","./preload-helper-PPVm8Dsz.js","./index-D5GCH8nj.css","./CrmParameterEditor-DO6Rt764.js","./crmParameters-rgfZhhzN.js","./useStableKeys-49o4VnxU.js","./RuleEditorPanel-BxGrJYo4.js","./ruleKinds-BKTUiZ1-.js","./ScriptView-tkdIK4sg.js","./MonacoEditor-DweI16yt.js","./TabDisplayRulesPanel-S_AxUWfB.js","./XmlView-B0weY9hR.js","./CompareView-CdQo0D6e.js","./TranslationsView-DZIGE2pC.js"])))=>i.map(i=>d[i]);
2
+ import{_ as y}from"./preload-helper-PPVm8Dsz.js";import{r as u,j as e,F as N,ar as V,k as j,m as E,t as l,T as w,ai as C,B as L,dZ as z,d_ as R,dX as v,ac as B,eK as P,eL as A,z as H,E as S,cH as F,l as O,eM as W,eN as X,dY as $,e as I,eO as M}from"./fluent-ui-CQyNN9H3.js";import{u as U,a as x,b as g,I as D,c as K,i as Y}from"./index-DRTwBo4g.js";import"./dnd-iy5K5XAJ.js";const Z=E({rename:{display:"flex",alignItems:"flex-start",gap:l.spacingHorizontalS,marginTop:l.spacingVerticalXS},field:{flex:1,minWidth:0},input:{fontFamily:l.fontFamilyMonospace},buttons:{display:"flex",gap:l.spacingHorizontalXS,marginTop:"22px"}});function q(s,i,m,p){if(!s.trim())return"Enter an ID.";if(/\s/.test(s))return"An ID can't contain spaces.";if(s!==i&&m.some(c=>c.toLowerCase()===s.toLowerCase()))return`Another ${p} already has this ID.`}function T({label:s,current:i,ids:m,what:p,hint:c,onRename:f,onDone:h}){const r=Z(),[a,b]=u.useState(i),o=q(a,i,m,p),n=()=>{const d=a.trim();!o&&d!==i&&f(d),h()};return e.jsxs("div",{className:r.rename,children:[e.jsx(N,{className:r.field,label:s,validationState:o?"error":"none",validationMessage:o,hint:o?void 0:c,children:e.jsx(V,{className:r.input,value:a,autoFocus:!0,onChange:(d,t)=>b(t.value),onKeyDown:d=>{d.key==="Enter"&&n(),d.key==="Escape"&&(d.stopPropagation(),h())}})}),e.jsxs("div",{className:r.buttons,children:[e.jsx(j,{appearance:"primary",disabled:!!o||a.trim()===i,onClick:n,children:"Rename"}),e.jsx(j,{onClick:h,children:"Cancel"})]})]})}const G=E({idRow:{display:"flex",alignItems:"center",gap:l.spacingHorizontalS,minWidth:0,marginTop:l.spacingVerticalXS},id:{flex:1,minWidth:0},badge:{flexShrink:0},tabs:{marginTop:l.spacingVerticalS,marginLeft:`calc(-1 * ${l.spacingHorizontalM})`}}),J={custom:{text:"Yours",color:"success"},customising:{text:"Your copy",color:"brand"},customised:{text:"Your copy",color:"brand"},oob:{text:"Read-only",color:"informative"},uncustomising:{text:"Read-only",color:"informative"},reloadRequired:{text:"Read-only",color:"informative"}};function Q({commandId:s}){const i=G(),m=U(s)?.provenance,p=x(t=>t.commands.find(_=>_.id===s)),c=x(t=>K(t.ribbons,s).length),f=g(t=>t.commandEditorTab),h=g(t=>t.setCommandEditorTab),r=x(t=>t.commands).map(t=>t.id),a=x(t=>t.renameCommandId),b=g(t=>t.openCommandEditor),[o,n]=u.useState(!1),d=m&&J[m];return e.jsxs(e.Fragment,{children:[o?e.jsx(T,{label:"Command ID",current:s,ids:r,what:"command",hint:"Usually publisher.Table.Button.Command. Its buttons follow the new ID.",onRename:t=>a(s,t)&&b(t),onDone:()=>n(!1)}):e.jsxs("div",{className:i.idRow,children:[e.jsx("div",{className:i.id,children:e.jsx(D,{label:"Command ID",value:s,hideLabel:!0,action:m==="custom"&&e.jsx(w,{content:"Rename command ID",relationship:"label",children:e.jsx(j,{appearance:"subtle",icon:e.jsx(C,{}),onClick:()=>n(!0)})})})}),d&&e.jsx(L,{appearance:"tint",color:d.color,size:"medium",className:i.badge,children:d.text})]}),e.jsxs(z,{className:i.tabs,selectedValue:f,onTabSelect:(t,_)=>h(_.value),children:[e.jsx(R,{value:"actions",children:"Actions"}),e.jsxs(R,{value:"enable",children:["Enable rules (",p?.enableRules.length??0,")"]}),e.jsxs(R,{value:"display",children:["Display rules (",p?.displayRules.length??0,")"]}),e.jsxs(R,{value:"usedBy",children:["Used by (",c,")"]})]})]})}const ee=E({idRow:{display:"flex",alignItems:"center",gap:l.spacingHorizontalS,minWidth:0,marginTop:l.spacingVerticalXS},id:{flex:1,minWidth:0},usedBy:{color:l.colorNeutralForeground3}});function ae({ruleId:s,kind:i}){const m=ee(),p=x(n=>i==="enable"?n.enableRules:n.displayRules),c=x(n=>n.commands.filter(d=>(i==="enable"?d.enableRules:d.displayRules).includes(s)).length),f=x(n=>n.renameEnableRuleId),h=x(n=>n.renameDisplayRuleId),r=g(n=>n.openRuleEditor),[a,b]=u.useState(!1),o=n=>{(i==="enable"?f(s,n):h(s,n))&&r(n,i)};return e.jsxs(e.Fragment,{children:[a?e.jsx(T,{label:"Rule ID",current:s,ids:p.map(n=>n.id),what:"rule",hint:"The commands that use it follow the new ID.",onRename:o,onDone:()=>b(!1)}):e.jsx("div",{className:m.idRow,children:e.jsx("div",{className:m.id,children:e.jsx(D,{label:"Rule ID",value:s,hideLabel:!0,action:!Y(s)&&e.jsx(w,{content:"Rename rule ID",relationship:"label",children:e.jsx(j,{appearance:"subtle",icon:e.jsx(C,{}),onClick:()=>b(!0)})})})})}),e.jsxs(v,{className:m.usedBy,children:["Used by ",c," command",c===1?"":"s"]})]})}const se=u.lazy(()=>y(()=>import("./CommandEditorPanel-DYsxUTOk.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8]),import.meta.url)),ne=u.lazy(()=>y(()=>import("./RuleEditorPanel-BxGrJYo4.js"),__vite__mapDeps([9,1,3,4,2,5,10,6,7,8]),import.meta.url)),ie=u.lazy(()=>y(()=>import("./ScriptView-tkdIK4sg.js"),__vite__mapDeps([11,1,3,4,2,5,12]),import.meta.url)),te=u.lazy(()=>y(()=>import("./TabDisplayRulesPanel-S_AxUWfB.js"),__vite__mapDeps([13,1,3,4,2,5,8]),import.meta.url)),oe=u.lazy(()=>y(()=>import("./XmlView-B0weY9hR.js"),__vite__mapDeps([14,1,3,4,2,5,12]),import.meta.url)),le=u.lazy(()=>y(()=>import("./CompareView-CdQo0D6e.js"),__vite__mapDeps([15,4,1,3,2,5]),import.meta.url)),re=u.lazy(()=>y(()=>import("./TranslationsView-DZIGE2pC.js"),__vite__mapDeps([16,1,3,4,2,5]),import.meta.url)),de=E({drawer:{width:"720px",maxWidth:"90vw"},wide:{width:"960px"},fill:{display:"flex",flexDirection:"column"},navigation:{justifyContent:"space-between"},title:{display:"flex",flexDirection:"column",gap:l.spacingVerticalXXS,minWidth:0},trail:{color:l.colorNeutralForeground3},idRow:{display:"flex",alignItems:"center",gap:l.spacingHorizontalS,minWidth:0,marginTop:l.spacingVerticalXS},id:{flex:1,minWidth:0},footer:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:l.spacingHorizontalM},hint:{color:l.colorNeutralForeground3}});function k(s){return s.kind==="command"?"Edit command":s.kind==="rule"?`Edit ${s.ruleKind} rule`:s.kind==="tabRules"?"Tab display rules":s.kind==="xml"?"XML of your changes":s.kind==="translations"?"Translations":s.kind==="diff"?s.id==="compare"?"Compare with published":"What this change did":s.editable?"Edit script":"View script"}function xe(){const s=de(),i=g(o=>o.editorStack),m=g(o=>o.editorBack),p=g(o=>o.closeEditor),c=i.length>0,[f,h]=u.useState(i);c&&i!==f&&h(i);const r=c?i:f,a=r[r.length-1],b=r[r.length-2];return u.useEffect(()=>c?(x.getState().beginEditSession(),()=>x.getState().endEditSession()):void 0,[c]),e.jsxs(B,{position:"end",open:c,onOpenChange:(o,n)=>!n.open&&p(),className:I(s.drawer,(a?.kind==="xml"||a?.kind==="diff")&&s.wide),"aria-label":a?k(a):"Editor",children:[e.jsxs(P,{children:[e.jsx(A,{children:e.jsxs(H,{className:s.navigation,children:[b?e.jsx(S,{appearance:"subtle",icon:e.jsx(F,{}),onClick:m,children:k(b)}):e.jsx("span",{}),e.jsx(S,{appearance:"subtle",icon:e.jsx(O,{}),"aria-label":"Close",onClick:p})]})}),a&&e.jsx(W,{children:e.jsxs("span",{className:s.title,children:[r.length>2&&e.jsxs(v,{className:s.trail,children:[r.slice(0,-1).map(k).join(" › ")," ›"]}),k(a)]})}),a?.kind==="command"&&e.jsx(Q,{commandId:a.id},a.id),a?.kind==="rule"&&e.jsx(ae,{ruleId:a.id,kind:a.ruleKind},a.id),(a?.kind==="script"||a?.kind==="tabRules"||a?.kind==="translations")&&e.jsx("div",{className:s.idRow,children:e.jsx("div",{className:s.id,children:e.jsx(D,{label:a.kind==="tabRules"?"Tab ID":a.kind==="translations"?"Button ID":"Web resource",value:a.id,hideLabel:!0})})})]}),e.jsx(X,{className:I((a?.kind==="script"||a?.kind==="xml"||a?.kind==="diff")&&s.fill),children:e.jsxs(u.Suspense,{fallback:e.jsx($,{size:"small",label:"Loading…"}),children:[a?.kind==="command"&&e.jsx(se,{}),a?.kind==="rule"&&e.jsx(ne,{}),a?.kind==="tabRules"&&e.jsx(te,{location:a.location,tabId:a.id}),a?.kind==="script"&&e.jsx(ie,{name:a.id,editable:a.editable},a.id),a?.kind==="xml"&&e.jsx(oe,{location:a.id},a.id),a?.kind==="translations"&&e.jsx(re,{buttonId:a.id},a.id),a?.kind==="diff"&&e.jsx(le,{historyIndex:a.historyIndex},`${a.id}:${a.historyIndex??""}`)]})}),e.jsxs(M,{className:s.footer,children:[e.jsx(v,{className:s.hint,children:a?.kind==="script"?a.editable?"Save writes the script to Dataverse · Undo doesn't revert it":"":a?.kind==="xml"||a?.kind==="diff"?"":"Changes apply as you edit · Ctrl Z to undo"}),e.jsx(j,{appearance:"primary",onClick:p,children:"Done"})]})]})}export{xe as EditorDrawer,xe as default};
@@ -0,0 +1 @@
1
+ import{j as c}from"./fluent-ui-CQyNN9H3.js";import{b as s,a as n,ak as b,aE as m,aF as p,am as f}from"./index-DRTwBo4g.js";import"./preload-helper-PPVm8Dsz.js";import"./dnd-iy5K5XAJ.js";const O=()=>{const o=s(e=>e.hideInsteadOfDelete),a=s(e=>e.closeHideInsteadOfDelete),i=s(e=>e.announce),t=n(e=>o?f(e.ribbons[o.location].tabs.find(d=>d.id===o.tabId)?.groups.find(d=>d.id===o.groupId),o.buttonId):void 0),l=n(e=>o?e.baseline[o.location]:void 0),r=n(e=>e.locLabels),u=b();return!o||!t||!l?null:c.jsx(m,{open:!0,buttonLabel:u(t.label,r,void 0,t.source?.labelToken),buttonId:t.id,commandId:t.commandId,deleteBlockedReason:p(t,l),onConfirmHide:()=>{n.getState().hideOobButton(o.location,o.tabId,o.groupId,o.buttonId),i("Button hidden"),a()},onConfirmDisplayRule:()=>{n.getState().hideWithDisplayRules(t.commandId)&&i("Button hidden"),a()},onCancel:a})};export{O as HideInsteadOfDeleteModal,O as default};
@@ -0,0 +1 @@
1
+ import{j as o,r as t,dD as se,W as ne,dZ as Ie,d_ as V,a6 as te,a7 as ie,dP as le,eP as We,d as $e,eR as ce,T as Te,k as C,e as U,c as M,dX as z,dY as Ne,F as Be,ar as Ee,p as Le,m as Pe,t as a}from"./fluent-ui-CQyNN9H3.js";import{u as Fe}from"./useReplaceWebResourceConfirm-BhU1AM5L.js";import{b as de,a as De,a2 as $,S as ue,ao as ge,Z as Ge,ap as pe,aq as H,ar as Ve,as as he,at as Ue,G as O,au as Me,av as ze,aw as He,ax as Oe,ay as _e,F as _}from"./index-DRTwBo4g.js";import"./preload-helper-PPVm8Dsz.js";import"./dnd-iy5K5XAJ.js";function Xe({text:s}){return o.jsx(o.Fragment,{children:s.split(/(?=[A-Z])/).map((h,c)=>o.jsxs(t.Fragment,{children:[c>0&&o.jsx("wbr",{}),h]},c))})}const Ze=[{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"]}],qe=["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 Ye(s){for(const h of Ze)if(h.keywords.some(c=>s.includes(c)))return h.category;return"General"}const me=qe.map(s=>({name:s,category:Ye(s)})),Qe=["All",...Array.from(new Set(me.map(s=>s.category))).sort()],Ke=Pe({content:{display:"flex",flexDirection:"column",gap:a.spacingVerticalS,height:"min(560px, calc(100vh - 240px))",minHeight:"320px",overflowY:"hidden"},toolbar:{display:"flex",alignItems:"center",gap:a.spacingHorizontalS,flexWrap:"wrap",flexShrink:0},search:{flex:"1 1 220px",minWidth:0},category:{minWidth:"160px"},variant:{display:"flex",gap:a.spacingHorizontalXS},iconGrid:{display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(88px, 1fr))",gap:a.spacingHorizontalXS,overflowY:"auto",flex:1,minHeight:0,padding:a.spacingHorizontalXXS},iconTile:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:a.spacingVerticalXS,minHeight:"72px",height:"auto",padding:a.spacingVerticalS,fontWeight:a.fontWeightRegular},iconTileSelected:{backgroundColor:a.colorBrandBackground2,border:`1px solid ${a.colorBrandStroke1}`},iconLabel:{fontSize:a.fontSizeBase200,textAlign:"center",lineHeight:a.lineHeightBase200,overflowWrap:"anywhere"},muted:{color:a.colorNeutralForeground3},selection:{display:"flex",alignItems:"center",gap:a.spacingHorizontalS,padding:`${a.spacingVerticalXS} ${a.spacingHorizontalS}`,backgroundColor:a.colorNeutralBackground3,borderRadius:a.borderRadiusMedium,flexShrink:0,minWidth:0},selectionText:{minWidth:0,display:"flex",flexDirection:"column"},resourceList:{listStyleType:"none",margin:0,padding:a.spacingHorizontalXXS,flex:1,minHeight:0,overflowY:"auto",display:"flex",flexDirection:"column",gap:a.spacingVerticalXXS},resourceRow:{width:"100%",justifyContent:"flex-start",fontFamily:a.fontFamilyMonospace,fontWeight:a.fontWeightRegular,fontSize:a.fontSizeBase200,textAlign:"start",overflowWrap:"anywhere"},dropZone:{flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:a.spacingVerticalM,padding:a.spacingVerticalL,textAlign:"center",border:`2px dashed ${a.colorNeutralStroke2}`,borderRadius:a.borderRadiusMedium,color:a.colorNeutralForeground3},dropZoneActive:{border:`2px dashed ${a.colorBrandStroke1}`,backgroundColor:a.colorBrandBackground2}}),X=300,so=()=>{const s=Ke(),h=Fe(),c=de(e=>e.iconPickerOpen),A=de(e=>e.closeIconPicker),Z=De(e=>e.setButtonProp),R=$(e=>e.selectedButtonId),I=$(e=>e.selectedGroupId),q=$(e=>e.tabId),Y=$(e=>e.location),T=ue(e=>e.publisherPrefix),v=ue(e=>e.activeSolution),[Q,d]=t.useState(null),[K,W]=t.useState(null),[g,J]=t.useState("fluent"),[N,fe]=t.useState(""),[w,Se]=t.useState("All"),[m,ee]=t.useState("regular"),[l,be]=t.useState(null),[f,B]=t.useState(""),[x,E]=t.useState([]),[we,oe]=t.useState(!1),[L,xe]=t.useState(""),[S,y]=t.useState(!1),[ye,P]=t.useState(!1),re=t.useRef(null),Ce=se({axis:"grid-linear"}),ve=se({axis:"vertical"});ne.useEffect(()=>{c||(d(null),W(null))},[c]),ne.useEffect(()=>{!c||g!=="webresource"||(oe(!0),ge("svg").then(e=>E(e)).catch(()=>E([])).finally(()=>oe(!1)))},[c,g]);const k=t.useMemo(()=>{const e=L.toLowerCase();return x.filter(r=>!e||r.name.toLowerCase().includes(e))},[L,x]),F=t.useMemo(()=>{const e=N.toLowerCase();return me.filter(r=>(w==="All"||r.category===w)&&(e===""||r.name.toLowerCase().includes(e)))},[N,w]),ke=async()=>{if(!l||!R||!I)return;const e=_(),r=O.getState();if(d(null),!v||v.isManaged){d("Select an unmanaged solution first — the icon is added to it as an SVG web resource.");return}y(!0);try{const n=await Me(l,m,T,ze,{busy:{onProgress:i=>r.logInfo("webresource",i)},guard:e});n.publishError&&r.logWarn("webresource",`Publishing icon web resource ${n.name} failed: ${n.publishError}. Pick the icon again or publish customizations before using the button.`),Z(Y,q,I,R,{icon:H(l),image16:`$webresource:${n.name}`,image32:`$webresource:${n.name}`}),r.logInfo("webresource",`${n.created?"Uploaded":"Reusing"} icon web resource ${n.name} (solution ${v.uniqueName}).`),A()}catch(n){const i=n instanceof Error?n.message:String(n);r.logError("webresource",`Fluent icon "${l}" could not be added as a web resource: ${i}`),d(`Could not add the icon as a web resource: ${i}`)}finally{y(!1)}},je=async()=>{if(!f||!R||!I)return;const e=he(f),r=_(),n=O.getState();d(null),W(null);const i=e.startsWith("$webresource:")?e.slice(13).trim():null;let p=null;if(i){y(!0);try{const b=x.find(D=>D.name===i),u=await He(i,b,r);u.solutionUniqueName&&n.logInfo("webresource",`Added web resource ${i} to solution ${u.solutionUniqueName}.`),p=u.solutionWarning??null}catch(b){const u=b instanceof Error?b.message:String(b);if(/^No web resource named /.test(u)){d(u);return}p=`The icon was set, but ${i} could not be added to the solution: ${u}`,n.logError("webresource",p)}finally{y(!1)}}if(Z(Y,q,I,R,{image16:e,image32:e}),p){W(p);return}A()},Ae=async e=>{const r=_();if(!v||v.isManaged){d("Select an unmanaged solution first — the SVG is added to it as a web resource.");return}d(null),y(!0);try{const n=await new Promise((u,D)=>{const j=new FileReader;j.onerror=()=>D(j.error??new Error("Failed to read SVG")),j.onload=()=>{const G=String(j.result??"");u(G.includes(",")?G.split(",")[1]??"":G)},j.readAsDataURL(e)}),i=`${T||"new"}_/icons/${e.name}`,p=await Oe(i,n,11,{displayName:e.name,guard:r,onExisting:h.onExisting});W([p.solutionWarning,p.publishWarning].filter(Boolean).join(" ")||null),B(`$webresource:${i}`),J("webresource");const b=await ge("svg");E(b)}catch(n){if(n instanceof _e)return;const i=n instanceof Error?n.message:String(n);O.getState().logError("webresource",`SVG upload failed: ${i}`),d(`Upload failed: ${i}`)}finally{y(!1)}},ae=e=>{if(e){if(!/\.svg$/i.test(e.name)){d(`${e.name} isn't an SVG file.`);return}Ae(e)}},Re=f.startsWith("$webresource:")?f.slice(13):f;return o.jsxs(o.Fragment,{children:[h.dialog,o.jsxs(Ge,{open:c,onOpenChange:e=>!e&&A(),title:"Choose an icon",size:"large",contentClassName:s.content,startActions:o.jsx(Ue,{prefix:"Saves to"}),actions:o.jsxs(o.Fragment,{children:[o.jsx(C,{onClick:A,children:"Cancel"}),g==="fluent"&&o.jsx(C,{appearance:"primary",disabled:!l||S,onClick:()=>{ke()},children:S?"Adding icon…":`Use ${l??"icon"}`}),g==="webresource"&&o.jsx(C,{appearance:"primary",disabled:!f||S,onClick:()=>{je()},children:S?"Adding icon…":"Use web resource"})]}),children:[o.jsxs(Ie,{selectedValue:g,onTabSelect:(e,r)=>J(r.value),children:[o.jsx(V,{value:"fluent",children:"Fluent icons"}),o.jsx(V,{value:"webresource",children:"Web resources"}),o.jsx(V,{value:"upload",children:"Upload SVG"})]}),Q&&o.jsx(te,{intent:"error",children:o.jsx(ie,{children:Q})}),K&&o.jsx(te,{intent:"warning",children:o.jsxs(ie,{children:["Icon applied. ",K]})}),g==="fluent"&&o.jsxs(o.Fragment,{children:[o.jsxs("div",{className:s.toolbar,children:[o.jsx(le,{className:s.search,placeholder:"Search icons","aria-label":"Search icons",value:N,onChange:(e,r)=>fe(r.value)}),o.jsx(We,{className:s.category,"aria-label":"Category",value:w==="All"?"All categories":w,selectedOptions:[w],onOptionSelect:(e,r)=>Se(String(r.optionValue??"All")),children:Qe.map(e=>o.jsx($e,{value:e,text:e==="All"?"All categories":e,children:e==="All"?"All categories":e},e))}),o.jsxs("div",{className:s.variant,role:"group","aria-label":"Icon style",children:[o.jsx(ce,{checked:m==="regular",onClick:()=>ee("regular"),children:"Regular"}),o.jsx(ce,{checked:m==="filled",onClick:()=>ee("filled"),children:"Filled"})]})]}),o.jsxs("div",{className:s.iconGrid,role:"group","aria-label":`${F.length} icons`,...Ce,children:[F.map(e=>{const r=l===e.name;return o.jsx(Te,{content:`${e.name} · ${e.category}`,relationship:"description",children:o.jsxs(C,{appearance:"subtle","aria-pressed":r,className:U(s.iconTile,r&&s.iconTileSelected),onClick:()=>be(e.name),children:[o.jsx(pe,{name:H(e.name),size:24,variant:m}),o.jsx("span",{className:s.iconLabel,children:o.jsx(Xe,{text:e.name})})]})},e.name)}),F.length===0&&o.jsx(M,{className:s.muted,children:"No icon matches."})]}),l&&o.jsxs("div",{className:s.selection,role:"status",children:[o.jsx(pe,{name:H(l),size:24,variant:m}),o.jsxs("span",{className:s.selectionText,children:[o.jsxs(M,{weight:"semibold",children:[l," ·"," ",m==="regular"?"Regular":"Filled"]}),o.jsxs(z,{className:s.muted,children:["Added to your solution as"," ",Ve(T||"new",l,m)]})]})]})]}),g==="webresource"&&o.jsxs(o.Fragment,{children:[o.jsx(le,{placeholder:"Search SVG web resources","aria-label":"Search SVG web resources",value:L,onChange:(e,r)=>xe(r.value)}),we?o.jsx(Ne,{size:"small",label:"Loading web resources…"}):o.jsxs(o.Fragment,{children:[o.jsx(z,{className:s.muted,role:"status",children:k.length>X?`Showing ${X} of ${k.length.toLocaleString()} SVG web resources. Search to find others.`:k.length===x.length?`${x.length.toLocaleString()} SVG web resources`:`${k.length} of ${x.length.toLocaleString()} SVG web resources`}),o.jsx("ul",{className:s.resourceList,"aria-label":"SVG web resources",...ve,children:k.slice(0,X).map(e=>{const r=`$webresource:${e.name}`,n=f===r;return o.jsx("li",{children:o.jsx(C,{appearance:"subtle","aria-pressed":n,className:U(s.resourceRow,n&&s.iconTileSelected),onClick:()=>B(r),children:e.name})},e.id)})})]}),o.jsx(Be,{label:"Web resource",hint:"Image16 and Image32 are both set to it. SVG works at every size.",children:o.jsx(Ee,{placeholder:"publisher_/icons/icon.svg",value:Re,onChange:(e,r)=>B(r.value?he(r.value):"")})})]}),g==="upload"&&o.jsxs("div",{className:U(s.dropZone,ye&&s.dropZoneActive),onDragOver:e=>{e.preventDefault(),P(!0)},onDragLeave:()=>P(!1),onDrop:e=>{e.preventDefault(),P(!1),ae(e.dataTransfer.files?.[0])},children:[o.jsx(Le,{fontSize:48}),o.jsx(M,{children:"Drop an SVG file here"}),o.jsx(z,{children:"It's uploaded as a web resource in your solution, then listed under Web resources to use."}),o.jsx("input",{ref:re,type:"file",accept:".svg",hidden:!0,disabled:S,onChange:e=>{const r=e.target.files?.[0];e.target.value="",ae(r)}}),o.jsx(C,{appearance:"primary",disabled:S,onClick:()=>re.current?.click(),children:S?"Uploading…":"Choose SVG…"})]})]})]})};export{so as IconPickerModal,so as default};
@@ -0,0 +1 @@
1
+ import{r as W,j as c,c as k,dX as de,a6 as ze,a7 as Fe,B as Ne,k as _,m as Pe,t as E}from"./fluent-ui-CQyNN9H3.js";import{a9 as ve,v as We,aa as Ue,ab as _e,ac as Je,ad as Ye,ae as Ke,b as ne,S as De,Z as Ve,a as Ze,a2 as Qe}from"./index-DRTwBo4g.js";import{a as et}from"./xmlValidator-CnbyWxHe.js";import{M as tt}from"./MonacoEditor-DweI16yt.js";import"./preload-helper-PPVm8Dsz.js";import"./dnd-iy5K5XAJ.js";import"./ruleKinds-BKTUiZ1-.js";import"./crmParameters-rgfZhhzN.js";const ge=["HomepageGrid","SubGrid","Form"],ue=[...ge,"Application"],pe=new Set(["Button","FlyoutAnchor","SplitButton","TextBox","ComboBox","CheckBox"]),me=new Set(["flyout","splitButton"]),he=/^Mscrm\.(HomepageGrid|SubGrid|Form)\.([^.]+)\./,Ie="._children",ot=/<(EnableRule|DisplayRule)\b[^>]*?\sId="([^"]+)"/,be=/\$LocLabels:([^"'\s<]+)/g,Le="cbs.import.Tab",nt="cbs.import.Group",je=(i,b)=>JSON.stringify(i)===JSON.stringify(b);function U(i){return i?Array.from(i.children):[]}function st(i){return Object.fromEntries(Array.from(i.attributes).map(b=>[b.name,b.value]))}function it(i,b,d){const m=i.documentElement;if(m.tagName==="RibbonDiffXml")return m;const h=Array.from(i.getElementsByTagName("RibbonDiffXml")),$=Array.from(i.querySelectorAll("Entities > Entity")).flatMap(l=>{const A=U(l),O=A.find(I=>I.tagName==="RibbonDiffXml"),T=A.find(I=>I.tagName==="Name")?.textContent?.trim()??"";return O?[{name:T,rdx:O}]:[]}),w=h.find(l=>l.parentElement===m);if($.length===0&&!w){if(h.length===1)return h[0];throw new Error(h.length===0?"No <RibbonDiffXml> element found.":`The XML has ${h.length} <RibbonDiffXml> elements and none belongs to a table or the application ribbon — paste just one.`)}const G=[...$.map(l=>l.name||"(unnamed table)"),...w?["the application ribbon"]:[]].join(", ");if(d){if(w)return w;throw new Error(`The XML has no application ribbon RibbonDiffXml (it has: ${G}). Open that table's ribbon to import its customizations.`)}const S=$.find(l=>l.name.toLowerCase()===b.toLowerCase());if(S)return S.rdx;throw new Error(`The XML has no RibbonDiffXml for ${b||"the loaded table"} (it has: ${G}). Load that table, or open the application ribbon for the application ribbon's customizations.`)}function rt(i){switch(i){case"HomePageGrid":return"HomepageGrid";case"Form":return"Form";case"SubGridStandard":case"SubGridAssociated":return"SubGrid";default:return}}function at(i){const b=i.languageCode??1033,d=i.entityLogicalName,m=new DOMParser().parseFromString(i.xml,"application/xml");if(m.querySelector("parsererror"))throw new Error("The XML is not well-formed.");const h=i.activeLocation==="Application",$=it(m,d,h),w=new XMLSerializer,G=w.serializeToString($),S=[],l=[],A=[],O=!!d&&new RegExp(`Mscrm\\.(HomepageGrid|SubGrid|Form)\\.${d.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\.`,"i").test(G),T=h&&!($===m.documentElement&&O);$!==m.documentElement?A.push(`Imported the RibbonDiffXml of ${T?"the application ribbon":d} from the document.`):h&&!T&&A.push(`The XML's Locations name the ${d} table, so it was imported as that table's customizations, not the application ribbon's.`);const I=T?"Application":ge.includes(i.activeLocation)?i.activeLocation:"HomepageGrid",B=ve(G,i.activeLocation,d),H=(e,t,o)=>{const s=new Map,n=new Map;for(const y of t)s.set(y.id,y),n.set(y.id,(n.get(y.id)??0)+1);for(const[y,x]of n)x>1&&A.push(`${o} ${y} is defined ${x} times in the XML — the last one was used.`);const u=Array.from(s.values()),a=[...e],p=[];let f=0;for(const y of u){const x=a.findIndex(D=>D.id===y.id);if(x>=0&&je(a[x],y)){f++;continue}S.push(`${o} ${y.id} ${x>=0?"updated":"added"}`),x>=0?a[x]=y:a.push(y),p.push(y.id)}return{out:a,changedIds:p,unchanged:f}},L=H(i.commands,B.commands,"Command"),z=H(i.enableRules,B.enableRules,"Enable rule"),N=H(i.displayRules,B.displayRules,"Display rule"),C=H(i.locLabels,B.locLabels,"Label"),X=C.out,q=L.unchanged+z.unchanged+N.unchanged+C.unchanged,M=(e,t)=>e&&Ke(e,X,b)||t,j=JSON.parse(JSON.stringify(i.ribbons));let v=!1,F=0;const r=new Set,g=e=>{if(T)return ue.slice().reverse();const t=he.exec(e),o=t&&t[2]!=="{!EntityLogicalName}"?t[1]:I;return[o,...ge.filter(s=>s!==o),"Application"]},R=(e,t)=>{T&&e!=="Application"?A.push(`${t} is on the table's ribbon (${e}), not the application ribbon: the change is published with the table.`):!T&&e==="Application"&&A.push(`${t} was found only on the application ribbon: the change is published to the application ribbon and affects every table.`)},ie=[],P=(e,t)=>{e&&e!==t&&ie.push(e)},J=e=>{for(const t of g(e))for(const o of j[t].tabs){const s=o.groups.find(n=>n.id===e);if(s)return{location:t,tab:o,group:s}}},Y=e=>{for(const t of g(e)){const o=j[t].tabs.find(s=>s.id===e);if(o)return{location:t,tab:o}}},K=e=>{for(const t of g(e)){const o=[];for(const s of j[t].tabs)for(const n of s.groups)for(const u of n.buttons)u.id===e&&o.push({group:n,button:u});if(o.length>0)return{location:t,found:o}}},V=(e,t)=>{const o=he.exec(t);let s="it isn't in the loaded ribbon";o&&o[2]!=="{!EntityLogicalName}"&&d&&o[2]!==d?s=`it belongs to the ${o[2]} table, but ${d} is loaded`:(o?.[2]==="{!EntityLogicalName}"||t.startsWith("Mscrm.Global"))&&(s="it belongs to the application ribbon, which isn't loaded with it"),l.push(`${e}: Location "${t}" not found — ${s}.`)},Ee=U($.querySelector(":scope > RuleDefinitions > TabDisplayRules")).map(e=>w.serializeToString(e)).join(""),re=e=>ve(`<RibbonDiffXml><UI><Ribbon><Tabs>${e}</Tabs></Ribbon></UI><RuleDefinitions><TabDisplayRules>${Ee}</TabDisplayRules></RuleDefinitions></RibbonDiffXml>`,i.activeLocation,d,X).ribbon.tabs[0],Z=e=>w.serializeToString(e),ye=e=>re(`<Tab Id="${Le}"><Groups><Group Id="${nt}"><Controls>${Z(e)}</Controls></Group></Groups></Tab>`)?.groups[0]?.buttons.find(t=>t.id===e.getAttribute("Id")),xe=e=>{const t=e.source;t&&(e.label=M(t.labelToken,e.id),t.tooltipTitleToken&&(e.tooltipTitle=M(t.tooltipTitleToken,"")),t.tooltipBodyToken&&(e.tooltipBody=M(t.tooltipBodyToken,"")))},Q=e=>{for(const t of e.source?.xml?[e.source.xml]:Object.values(e.source?.attributes??{}))for(const[,o]of t.matchAll(be))X.some(s=>s.id===o)||l.push(`${e.id}: references label ${o}, which neither the XML nor the loaded ribbon defines — add its <LocLabel>, or its text won't show unless another solution defines it (the pre-publish check warns).`)},$e=e=>({titleToken:e.getAttribute("Title")??void 0,attributes:st(e)}),Ae=(e,t)=>(Ye(e,{origin:"unmanaged"}),e.hidden=!1,t!==void 0&&!e.source?.attributes.Sequence&&(e.sequence=t),xe(e),Q(e),e),ae=e=>l.push(`${e}: flyout / split buttons and their menus can't be imported yet (#27).`),Oe=(e,t)=>{const o=new Set(Array.from(e.querySelectorAll("Menu *")).map(n=>n.getAttribute("Id")).filter(n=>!!n)),s=[];for(const n of t?.buttons??[])o.has(n.id)||(me.has(n.kind)?ae(n.id):s.push(Ae(n)));return s},ee=(e,t)=>{const o=e.findIndex(s=>s.sequence>t.sequence);e.splice(o<0?e.length:o,0,t)},we=(e,t,o)=>{const s=K(e),n=ye(t);if(!s||!n)return!1;xe(n),Q(n),R(s.location,e);for(const{group:u,button:a}of s.found){if(n.kind!==a.kind)return l.push(`${e}: changing a <${t.tagName}> into another kind of control isn't supported.`),!0;if(me.has(a.kind))return ae(e),!0;const p=JSON.parse(JSON.stringify(a));Object.assign(a,{label:n.label,tooltipTitle:n.tooltipTitle,tooltipBody:n.tooltipBody,icon:n.icon,image16:n.image16,image32:n.image32,commandId:n.commandId,templateAlias:n.templateAlias||a.templateAlias,source:structuredClone(n.source)});const f=n.source?.attributes.Sequence?n.sequence:o;f!==void 0&&f!==a.sequence&&(a.origin==="unmanaged"?(u.buttons.splice(u.buttons.indexOf(a),1),a.sequence=f,ee(u.buttons,a)):l.push(`${e}: Sequence ${f} not applied — only your own buttons can be re-ordered.`)),Je(p,a)||p.sequence!==a.sequence?(v=!0,S.push(`Updated ${a.label} (${e}) on ${s.location}`),n.templateAlias||A.push(`${e}: the override has no TemplateAlias — ${a.templateAlias} from the loaded control is kept.`)):(Object.assign(a,p),je(p.source?.attributes,n.source?.attributes)?F++:l.push(`${e}: the override only changes attributes CBS doesn't publish yet (label, tooltip, icon, command and template alias are).`))}return!0},Ce=(e,t,o,s)=>{const n=t.getAttribute("Id");if(!n)return l.push(`CustomAction ${e.getAttribute("Id")}: the control has no Id.`);const u=K(n);if(u){u.found.some(f=>f.group.id===o)||l.push(`${n}: already in group ${u.found[0].group.id} — updated there, not moved to ${o}.`),we(n,t,s)&&P(e.getAttribute("Id"),`${n}.Override.CustomAction`);return}const a=J(o);if(!a)return V(`${n}`,e.getAttribute("Location")??"");const p=ye(t);if(!p)return l.push(`${n}: couldn't read the <${t.tagName}>.`);if(me.has(p.kind))return ae(n);ee(a.group.buttons,Ae(p,s)),R(a.location,n),P(e.getAttribute("Id"),`${n}.CustomAction`),v=!0,S.push(`Added ${p.label} (${n}) to ${a.group.id} on ${a.location}`)},Se=(e,t)=>{const o=re(`<Tab Id="${Le}"><Groups>${Z(e)}</Groups></Tab>`)?.groups[0];if(!o)return;const s=$e(e);return Q({id:o.id,source:s}),{...o,label:M(s.titleToken,o.id),source:s,sequence:e.getAttribute("Sequence")===null?t??o.sequence:o.sequence,buttons:Oe(e,o)}},Xe=(e,t,o,s)=>{const n=t.getAttribute("Id");if(!n)return l.push(`CustomAction ${e.getAttribute("Id")}: the group has no Id.`);if(J(n)){l.push(`Group ${n} already exists — it was left as is (re-titling groups isn't supported).`);for(const f of U(t.querySelector(":scope > Controls")))pe.has(f.tagName)?Ce(e,f,n,void 0):Ue(_e[f.tagName])&&l.push(`${f.getAttribute("Id")??"(no Id)"}: adding a <${f.tagName}> to an existing group isn't supported — Command Bar Studio shows it read-only.`);return}const a=Y(o);if(!a)return V(`Group ${n}`,e.getAttribute("Location")??"");const p=Se(t,s);if(!p)return l.push(`Group ${n}: couldn't read the <Group>.`);ee(a.tab.groups,p),R(a.location,n),P(e.getAttribute("Id"),`${n}.CustomAction`),v=!0,S.push(`Added group ${p.label} (${n}) with ${p.buttons.length} control(s) to ${o} on ${a.location}`)},ke=(e,t,o)=>{const s=t.getAttribute("Id");if(!s)return l.push(`CustomAction ${e.getAttribute("Id")}: the tab has no Id.`);if(Y(s))return l.push(`Tab ${s} already exists — it was left as is.`);const n=re(Z(t));if(!n)return l.push(`Tab ${s}: couldn't read the <Tab>.`);const u=n.tabDisplayRules.flatMap(D=>D.rules.map(Te=>Te.kind==="EntityRule"?rt(Te.context):void 0)),a=T?"Application":u.find(D=>!!D)??he.exec(s)?.[1]??I,f=Array.from(t.querySelectorAll(":scope > Groups > Group")).map(D=>Se(D,void 0)).filter(D=>!!D),y=$e(t);Q({id:s,source:y});const x={...n,label:M(y.titleToken,s),source:y,sequence:t.getAttribute("Sequence")===null?o??n.sequence:n.sequence,groups:f};ee(j[a].tabs,x),P(e.getAttribute("Id"),`${s}.CustomAction`),x.commandId&&(r.add(x.commandId),L.out.some(D=>D.id===x.commandId)||(L.out.push({id:x.commandId,enableRules:[],displayRules:[],actions:[]}),L.changedIds.push(x.commandId),A.push(`Tab ${s}: its Command ${x.commandId} has no CommandDefinition in the XML — an empty one was added.`))),v=!0,S.push(`Added tab ${x.label} (${s}) with ${f.length} group(s) to ${a}`),t.querySelector(":scope > Scaling > Scale")&&l.push(`Tab ${s}: its <Scale> steps weren't imported — CBS writes a default MaxSize for each group.`)},Ge=e=>{const t=e.getAttribute("Location")??"",o=K(t);if(o){const s=o.found.filter(n=>!n.button.hidden);for(const n of s)n.button.hidden=!0;s.length>0?(R(o.location,t),P(e.getAttribute("HideActionId"),`${t}.HideAction`),v=!0,S.push(`Hid ${s[0].button.label} (${t}) on ${o.location}`)):F++;return}if(J(t)||Y(t))return l.push(`Hiding ${t}: hiding whole groups or tabs isn't supported yet — hide their buttons.`);l.push(`Hiding ${t}: not found in the loaded ribbon (it may belong to another table, or already be hidden by your customizations).`)},Me=e=>{const t=e.getAttribute("Id")??"(no Id)",o=e.getAttribute("Location")??"",s=e.getAttribute("Sequence"),n=s===null?void 0:parseInt(s,10),u=U(e.querySelector(":scope > CommandUIDefinition"))[0];if(!u)return l.push(`CustomAction ${t}: no <CommandUIDefinition> content.`);const a=u.tagName;if(o.endsWith(Ie)){const p=o.slice(0,-Ie.length);return p.endsWith(".Controls")&&pe.has(a)?Ce(e,u,p.slice(0,-9),n):p.endsWith(".Groups")&&a==="Group"?Xe(e,u,p.slice(0,-7),n):p==="Mscrm.Tabs"&&a==="Tab"?ke(e,u,n):p.endsWith(".Scaling")&&(a==="MaxSize"||a==="Scale")?l.push(`CustomAction ${t}: <${a}> scaling isn't imported — CBS writes a default MaxSize for each new group.`):l.push(`CustomAction ${t}: a <${a}> at "${o}" isn't supported.`)}if(pe.has(a)&&u.getAttribute("Id")===o){if(we(o,u,n)){P(t,`${o}.Override.CustomAction`);return}return V(`Override ${t}`,o)}return K(o)||J(o)||Y(o)?l.push(`CustomAction ${t}: replacing ${o} with a <${a}> isn't supported — only overriding a control with the same Id is.`):V(`CustomAction ${t}`,o)},Be=U($.querySelector(":scope > CustomActions"));for(const e of Be)e.tagName==="CustomAction"?Me(e):e.tagName==="HideCustomAction"?Ge(e):l.push(`<${e.tagName}> in CustomActions isn't supported.`);const te=new Set;for(const e of ue)for(const t of j[e].tabs)for(const o of t.groups)for(const s of o.buttons)for(const n of We(s))te.add(n);for(const e of r)te.add(e);const le=new Set,ce=new Set;for(const e of L.out)if(te.has(e.id)){e.enableRules.forEach(t=>le.add(t)),e.displayRules.forEach(t=>ce.add(t));for(const t of e.rawRuleRefs??[]){const o=ot.exec(t.xml);o&&(o[1]==="EnableRule"?le:ce).add(o[2])}}const oe=(e,t,o,s)=>{for(const n of e)t.has(n)||l.push(`${o} ${n} was imported but ${s}, so it won't be published.`)};oe(L.changedIds,te,"Command","no button on the loaded ribbon uses it"),oe(z.changedIds,le,"Enable rule","no command a button uses references it"),oe(N.changedIds,ce,"Display rule","no command a button uses references it");const Re=new Set(Array.from(Z($).matchAll(be),e=>e[1]));for(const e of ue)for(const t of j[e].tabs)for(const o of t.groups)for(const s of o.buttons)for(const n of Object.values(s.source?.attributes??{}))for(const u of n.matchAll(be))Re.add(u[1]);oe(C.changedIds,Re,"Label","nothing references it");const qe=Array.from($.querySelectorAll(":scope > RuleDefinitions > TabDisplayRules > TabDisplayRule"));for(const e of qe){const t=e.getAttribute("TabCommand")??"";r.has(t)||l.push(`TabDisplayRule for ${t}: only the display rules of tabs this import adds are imported.`);const o=U(e).filter(s=>s.tagName!=="EntityRule"&&s.tagName!=="PageRule");o.length>0&&l.push(`TabDisplayRule for ${t}: ${o.map(s=>`<${s.tagName}>`).join(", ")} not imported — only EntityRule and PageRule are supported.`)}ie.length>0&&A.push(`Ids normalised: CBS publishes CustomAction / HideCustomAction ids as {control}.CustomAction, {control}.Override.CustomAction and {control}.HideAction, so ${ie.join(", ")} will be written under those ids.`),q+F>0&&S.push(`${q+F} control(s) / definition(s) were already up to date`);const He=v||L.changedIds.length+z.changedIds.length+N.changedIds.length+C.changedIds.length>0;return{ribbons:v?j:i.ribbons,commands:L.out,enableRules:z.out,displayRules:N.out,locLabels:X,applied:S,notApplied:l,notes:A,changed:He}}function lt(i,b){const d=Ze.getState(),m=at({xml:i,ribbons:d.ribbons,commands:d.commands,enableRules:d.enableRules,displayRules:d.displayRules,locLabels:d.locLabels,entityLogicalName:De.getState().activeEntity?.logicalName??d.ribbons.HomepageGrid.entityLogicalName,activeLocation:Qe.getState().location,languageCode:d.baseLanguageCode});return b&&m.changed&&d.applyImport(m,`${m.applied.length} change(s)`),m}const ct=Pe({content:{display:"grid",gridTemplateColumns:"1.4fr 1fr",gap:E.spacingHorizontalL,height:"min(560px, calc(100vh - 240px))",minHeight:"320px",overflowY:"hidden","@media (max-width: 760px)":{gridTemplateColumns:"1fr",gridTemplateRows:"minmax(240px, 1.4fr) 1fr",overflowY:"auto"}},editorColumn:{display:"flex",flexDirection:"column",gap:E.spacingVerticalXS,minHeight:0,minWidth:0},editor:{flex:1,minHeight:"200px",border:`1px solid ${E.colorNeutralStroke2}`,borderRadius:E.borderRadiusMedium,overflow:"hidden"},muted:{color:E.colorNeutralForeground3},results:{display:"flex",flexDirection:"column",gap:E.spacingVerticalM,minHeight:0,minWidth:0,overflowY:"auto",paddingRight:E.spacingHorizontalXS},section:{display:"flex",flexDirection:"column",gap:E.spacingVerticalXS},list:{listStyleType:"none",margin:0,padding:0,display:"flex",flexDirection:"column",gap:E.spacingVerticalXS},row:{display:"flex",alignItems:"flex-start",gap:E.spacingHorizontalS,minWidth:0},rowBadge:{flexShrink:0,marginTop:"2px"},rowText:{minWidth:0,overflowWrap:"anywhere"},problemButton:{textAlign:"start",justifyContent:"flex-start",minWidth:0,height:"auto",padding:0,fontWeight:E.fontWeightRegular}});function fe(i){return/^Added\b|\badded$/.test(i)?"Add":/^Updated\b|\bupdated$/.test(i)?"Update":/^Hid\b/.test(i)?"Hide":null}const dt={Add:"success",Update:"brand",Hide:"informative"};function ut(i,b,d){const m=i.map(h=>{const $=h.lineHint?Number(/\d+/.exec(h.lineHint)?.[0]):void 0;return{severity:h.severity==="warning"?"warning":"error",text:h.message,line:Number.isFinite($)?$:void 0}});d&&m.push({severity:"error",text:d});for(const h of b?.notApplied??[])m.push({severity:"warning",text:h});return m}const se=(i,b)=>`${i} ${b}${i===1?"":"s"}`,$t=()=>{const i=ct(),b=ne(r=>r.importXmlOpen),d=ne(r=>r.importXmlSeed),m=ne(r=>r.importXmlNote),h=ne(r=>r.closeImportXml),$=De(r=>r.activeEntity?.displayName??r.activeEntity?.logicalName),[w,G]=W.useState(""),[S,l]=W.useState([]),[A,O]=W.useState(null),[T,I]=W.useState(""),B=W.useRef(null);W.useEffect(()=>{b&&(G(d),l([]),O(null),I(""))},[b,d]);const H=r=>{G(r),A?.imported||(O(null),l([]),I(""))},L=r=>{const g=et(w);if(l(g),I(""),g.some(R=>R.severity!=="warning")){O(null);return}try{O({result:lt(w,r),imported:r})}catch(R){O(null),I(R instanceof Error?R.message:String(R))}},z=r=>{const g=B.current;g&&(g.revealLineInCenter(r),g.setPosition({lineNumber:r,column:1}),g.focus())},N=A?.imported===!0,C=A?.result,X=C?.applied??[],q=ut(S,C,T),M=q.some(r=>r.severity==="error"),j=!!C||S.length>0||!!T,v=C&&!N?X.filter(r=>fe(r)).length:0,F=N?C.changed?`Imported ${se(X.filter(r=>fe(r)).length,"change")}`:"Nothing to import: the session already has all of it":j?`Preview · ${se(v,"change")}, ${se(q.length,"problem")}`:"Preview";return c.jsxs(Ve,{open:b,onOpenChange:r=>!r&&h(),title:"Import RibbonDiffXml",size:"large",contentClassName:i.content,actions:N?c.jsx(_,{appearance:"primary",onClick:h,children:"Close"}):c.jsxs(c.Fragment,{children:[c.jsx(_,{onClick:h,children:"Cancel"}),c.jsx(_,{onClick:()=>L(!1),disabled:!w.trim(),children:j?"Preview again":"Preview"}),c.jsx(_,{appearance:"primary",onClick:()=>L(!0),disabled:!w.trim()||M,children:v>0?`Import ${se(v,"change")}`:"Import"})]}),children:[c.jsxs("div",{className:i.editorColumn,children:[c.jsx(k,{weight:"semibold",id:"import-xml-label",children:"Paste RibbonDiffXml"}),c.jsxs(de,{className:i.muted,children:["From Ribbon Workbench or a solution's customizations.xml. Only"," ",$??"this table","'s part is used."]}),c.jsx("div",{className:i.editor,role:"group","aria-labelledby":"import-xml-label",children:c.jsx(tt,{language:"xml",value:w,onChange:H,readOnly:N,height:"100%",onMount:r=>{B.current=r},options:{wordWrap:"on",lineNumbers:"on",padding:{top:8}}})})]}),c.jsxs("section",{className:i.results,"aria-label":"Preview",children:[c.jsx(k,{weight:"semibold",role:"status",children:F}),!j&&c.jsxs(c.Fragment,{children:[m&&!w&&c.jsx(ze,{intent:"info",children:c.jsx(Fe,{children:m})}),c.jsx(k,{className:i.muted,children:"Preview shows what the import changes, and any problems, before anything changes. Commands, rules and labels are added or replaced by ID; buttons, groups and tabs are added to the ribbon; overrides and hides change the existing controls. The import is one change: Undo takes it all back."})]}),q.length>0&&c.jsxs("div",{className:i.section,children:[c.jsx(k,{weight:"semibold",children:"Problems"}),c.jsx("ul",{className:i.list,"aria-label":"Problems",children:q.map((r,g)=>c.jsxs("li",{className:i.row,children:[c.jsx(Ne,{className:i.rowBadge,size:"medium",appearance:"tint",color:r.severity==="error"?"danger":"warning",children:r.severity==="error"?"Error":"Warning"}),r.line?c.jsx(_,{appearance:"transparent",className:i.problemButton,onClick:()=>z(r.line),children:c.jsxs("span",{className:i.rowText,children:["Line ",r.line,": ",r.text]})}):c.jsx(k,{className:i.rowText,children:r.text})]},g))}),!M&&!N&&v>0&&C.notApplied.length>0&&c.jsx(de,{className:i.muted,children:"Warnings don't stop the import: they say what won't be imported or published."})]}),X.length>0&&c.jsxs("div",{className:i.section,children:[c.jsx(k,{weight:"semibold",children:N?"Imported":"Changes"}),c.jsx("ul",{className:i.list,"aria-label":"Changes",children:X.map((r,g)=>{const R=fe(r);return c.jsxs("li",{className:i.row,children:[R&&c.jsx(Ne,{className:i.rowBadge,size:"medium",appearance:"tint",color:dt[R],children:R}),c.jsx(k,{className:i.rowText,children:r})]},g)})})]}),C&&C.notes.length>0&&c.jsxs("div",{className:i.section,children:[c.jsx(k,{weight:"semibold",children:"Good to know"}),c.jsx("ul",{className:i.list,children:C.notes.map((r,g)=>c.jsx("li",{children:c.jsx(k,{className:i.rowText,children:r})},g))})]}),N&&C.changed&&c.jsx(de,{className:i.muted,children:"Review the changes on the canvas, then publish. Undo takes the whole import back."})]})]})};export{$t as ImportXmlModal,$t as default};
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./monacoSetup-BIq1zGyP.js","./monaco-cQE5XS3B.js","./fluent-ui-CQyNN9H3.js","./preload-helper-PPVm8Dsz.js","./monaco-DQA8g3bM.css"])))=>i.map(i=>d[i]);
2
+ import{_ as s}from"./preload-helper-PPVm8Dsz.js";import{j as t,r as _,dY as u,W as f}from"./fluent-ui-CQyNN9H3.js";import{b as h}from"./index-DRTwBo4g.js";const x=f.lazy(()=>s(()=>import("./monacoSetup-BIq1zGyP.js"),__vite__mapDeps([0,1,2,3,4]),import.meta.url).then(()=>s(()=>import("./monaco-cQE5XS3B.js").then(e=>e.i),__vite__mapDeps([1,2,3,4]),import.meta.url))),v=({language:e,value:a,onChange:r,readOnly:i=!1,height:m="100%",options:n={},onMount:d})=>{const p=h(o=>o.themeMode)==="dark"?"vs-dark":"vs",l={readOnly:i,minimap:{enabled:!1},wordWrap:e==="xml"?"on":"off",scrollBeyondLastLine:!1,automaticLayout:!0,...n},c=o=>{r&&o!==void 0&&r(o)};return t.jsx(_.Suspense,{fallback:t.jsx(u,{size:"medium",label:"Loading editor…"}),children:t.jsx(x,{height:m,language:e,value:a,theme:p,options:l,onChange:c,onMount:d})})};export{v as M};
@@ -0,0 +1 @@
1
+ import{r as B,j as e,F as j,ar as K,as as T,k as v}from"./fluent-ui-CQyNN9H3.js";import{b as C,a as i,a2 as b,S as p,Z as _,t as q,a3 as z,G as D}from"./index-DRTwBo4g.js";import"./preload-helper-PPVm8Dsz.js";import"./dnd-iy5K5XAJ.js";const H=()=>{const n=C(t=>t.newButtonGroupId),r=C(t=>t.closeNewButton),I=i(t=>t.createButton),w=i(t=>t.upsertCommand),y=i(t=>t.batch),N=b(t=>t.selectButtonInContext),E=p(t=>t.publisherPrefix),R=p(t=>t.activeSolution),s=b(t=>t.location),k=b(t=>t.tabId),F=p(t=>t.activeEntity),L=n!==null,[c,m]=B.useState("New Button"),[f,h]=B.useState("button"),P=()=>{if(!n||!s)return;const t=R?.publisherPrefix?.trim()||E?.trim()||"new",a=F?.logicalName??"global",l=i.getState().ribbons,A=i.getState().commands,x=new Set(A.map(o=>o.id));for(const o of Object.values(l))for(const d of o.tabs)for(const G of d.groups)for(const O of q(G))x.add(O.id);const{id:g,commandId:S}=z(t,a,s,c,x),u=l[s].tabs.find(o=>o.groups.some(d=>d.id===n))?.id??k;if(!l[s].tabs.some(o=>o.id===u)){D.getState().logError("canvas",`Could not add the button: group ${n} was not found.`),r();return}y(()=>{I({location:s,tabId:u,groupId:n,button:{id:g,label:c,kind:f,templateAlias:"o1",commandId:S,hidden:!1,oob:!1,custom:!0,managed:!1}}),w({id:S,enableRules:[],displayRules:[],actions:[]})}),N(s,u,n,g),m("New Button"),h("button"),r()};return e.jsxs(_,{open:L,onOpenChange:t=>!t&&r(),size:"small",title:"New button",actions:e.jsxs(e.Fragment,{children:[e.jsx(v,{appearance:"secondary",onClick:r,children:"Cancel"}),e.jsx(v,{appearance:"primary",onClick:P,disabled:!c.trim(),children:"Create button"})]}),children:[e.jsx(j,{label:"Label",required:!0,hint:"A command is created with it; edit it in the command editor.",children:e.jsx(K,{value:c,onChange:(t,a)=>m(a.value),"data-autofocus":!0})}),e.jsx(j,{label:"Kind",children:e.jsxs(T,{value:f,onChange:(t,a)=>h(a.value),children:[e.jsx("option",{value:"button",children:"Button"}),e.jsx("option",{value:"flyout",children:"Flyout"}),e.jsx("option",{value:"splitButton",children:"Split button"})]})})]})};export{H as NewButtonModal,H as default};
@@ -0,0 +1 @@
1
+ import{r as u,j as a,F as m,ar as G,as as g,k as d}from"./fluent-ui-CQyNN9H3.js";import{b,a as T,a2 as h,Z as C,a4 as S}from"./index-DRTwBo4g.js";import"./preload-helper-PPVm8Dsz.js";import"./dnd-iy5K5XAJ.js";const s="Mscrm.Templates.Flexible2",F=()=>{const x=b(e=>e.newGroupOpen),t=b(e=>e.closeNewGroup),j=T(e=>e.createGroup),n=h(e=>e.location),l=h(e=>e.tabId),[o,c]=u.useState("New Group"),[p,i]=u.useState(s),w=()=>{!n||!l||(j({location:n,tabId:l,group:{label:o,template:p,buttons:[]}}),c("New Group"),i(s),t())};return a.jsxs(C,{open:x,onOpenChange:e=>!e&&t(),size:"small",title:"New group",actions:a.jsxs(a.Fragment,{children:[a.jsx(d,{appearance:"secondary",onClick:t,children:"Cancel"}),a.jsx(d,{appearance:"primary",onClick:w,disabled:!o.trim(),children:"Create group"})]}),children:[a.jsx(m,{label:"Label",required:!0,children:a.jsx(G,{value:o,onChange:(e,r)=>c(r.value),"data-autofocus":!0})}),a.jsx(m,{label:"Group template",hint:"How the group's buttons shrink when the classic ribbon is narrow. Unified Interface ignores it.",children:a.jsx(g,{value:p,onChange:(e,r)=>i(r.value),children:S.map(e=>a.jsxs("option",{value:e,children:[e.replace(/^Mscrm\.Templates\./,""),e===s?" (recommended)":""]},e))})})]})};export{F as NewGroupModal,F as default};