@next-buildr/editor 2.0.0 → 3.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (645) hide show
  1. package/README.md +7 -0
  2. package/UPGRADING.md +322 -0
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/app/builder-editor.test.js +223 -18
  5. package/dist/app/config.d.ts +27 -4
  6. package/dist/app/config.d.ts.map +1 -1
  7. package/dist/app/config.js +4 -3
  8. package/dist/app/contracts.d.ts +40 -0
  9. package/dist/app/contracts.d.ts.map +1 -0
  10. package/dist/app/contracts.js +4 -0
  11. package/dist/app/editor-app.d.ts.map +1 -1
  12. package/dist/app/editor-app.js +316 -24
  13. package/dist/app/editor-app.test.js +144 -6
  14. package/dist/app/layout.d.ts +11 -2
  15. package/dist/app/layout.d.ts.map +1 -1
  16. package/dist/app/layout.js +170 -9
  17. package/dist/app/manifest.d.ts +7 -2
  18. package/dist/app/manifest.d.ts.map +1 -1
  19. package/dist/app/manifest.js +16 -4
  20. package/dist/app/shell-panels.d.ts +15 -0
  21. package/dist/app/shell-panels.d.ts.map +1 -1
  22. package/dist/app/small-screen.test.js +2 -2
  23. package/dist/app/stage-slots.d.ts +9 -0
  24. package/dist/app/stage-slots.d.ts.map +1 -0
  25. package/dist/app/stage-slots.js +10 -0
  26. package/dist/app/status-info.d.ts +2 -3
  27. package/dist/app/status-info.d.ts.map +1 -1
  28. package/dist/app/status-info.js +49 -16
  29. package/dist/canvas-host/canvas-frame.d.ts +13 -1
  30. package/dist/canvas-host/canvas-frame.d.ts.map +1 -1
  31. package/dist/canvas-host/canvas-frame.js +96 -8
  32. package/dist/canvas-host/canvas-frame.test.js +156 -3
  33. package/dist/canvas-host/host.d.ts +6 -0
  34. package/dist/canvas-host/host.d.ts.map +1 -1
  35. package/dist/canvas-host/host.js +116 -4
  36. package/dist/canvas-host/host.test.js +195 -6
  37. package/dist/clipboard/clipboard.d.ts +1 -1
  38. package/dist/clipboard/clipboard.d.ts.map +1 -1
  39. package/dist/clipboard/clipboard.js +5 -0
  40. package/dist/clipboard/clipboard.test.js +21 -1
  41. package/dist/clipboard/format.d.ts +3 -1
  42. package/dist/clipboard/format.d.ts.map +1 -1
  43. package/dist/clipboard/react.d.ts +1 -1
  44. package/dist/clipboard/react.d.ts.map +1 -1
  45. package/dist/clipboard/react.js +49 -3
  46. package/dist/dialogs/external-source.d.ts +15 -0
  47. package/dist/dialogs/external-source.d.ts.map +1 -0
  48. package/dist/dialogs/external-source.js +18 -0
  49. package/dist/dialogs/index.d.ts +4 -0
  50. package/dist/dialogs/index.d.ts.map +1 -1
  51. package/dist/dialogs/index.js +2 -0
  52. package/dist/dialogs/media-picker/index.d.ts +2 -2
  53. package/dist/dialogs/media-picker/index.d.ts.map +1 -1
  54. package/dist/dialogs/media-picker/index.js +1 -1
  55. package/dist/dialogs/media-picker/media-picker.d.ts +5 -0
  56. package/dist/dialogs/media-picker/media-picker.d.ts.map +1 -1
  57. package/dist/dialogs/media-picker/media-picker.js +67 -5
  58. package/dist/dialogs/media-picker/media-picker.test.js +72 -1
  59. package/dist/dialogs/media-picker/media-ref.d.ts +15 -0
  60. package/dist/dialogs/media-picker/media-ref.d.ts.map +1 -1
  61. package/dist/dialogs/media-picker/media-ref.js +29 -0
  62. package/dist/dialogs/remove-confirm.d.ts +14 -0
  63. package/dist/dialogs/remove-confirm.d.ts.map +1 -0
  64. package/dist/dialogs/remove-confirm.js +42 -0
  65. package/dist/dialogs/remove-confirm.test.d.ts +2 -0
  66. package/dist/dialogs/remove-confirm.test.d.ts.map +1 -0
  67. package/dist/dialogs/remove-confirm.test.js +118 -0
  68. package/dist/dnd/dnd-react.test.js +11 -2
  69. package/dist/dnd/dnd.test.js +23 -0
  70. package/dist/dnd/engine.d.ts +4 -2
  71. package/dist/dnd/engine.d.ts.map +1 -1
  72. package/dist/dnd/engine.js +6 -0
  73. package/dist/dnd/move-to-dialog.d.ts +4 -3
  74. package/dist/dnd/move-to-dialog.d.ts.map +1 -1
  75. package/dist/dnd/move-to-dialog.js +67 -10
  76. package/dist/dnd/react.d.ts.map +1 -1
  77. package/dist/dnd/react.js +5 -0
  78. package/dist/i18n/diagnostics.d.ts +22 -0
  79. package/dist/i18n/diagnostics.d.ts.map +1 -0
  80. package/dist/i18n/diagnostics.js +153 -0
  81. package/dist/i18n/diagnostics.test.d.ts +2 -0
  82. package/dist/i18n/diagnostics.test.d.ts.map +1 -0
  83. package/dist/i18n/diagnostics.test.js +74 -0
  84. package/dist/i18n/label-catalog.d.ts +20 -0
  85. package/dist/i18n/label-catalog.d.ts.map +1 -0
  86. package/dist/i18n/label-catalog.js +1 -0
  87. package/dist/i18n/locale-name.d.ts +7 -0
  88. package/dist/i18n/locale-name.d.ts.map +1 -0
  89. package/dist/i18n/locale-name.js +31 -0
  90. package/dist/i18n/localize-manifest.d.ts +11 -0
  91. package/dist/i18n/localize-manifest.d.ts.map +1 -0
  92. package/dist/i18n/localize-manifest.js +78 -0
  93. package/dist/i18n/localize-manifest.test.d.ts +2 -0
  94. package/dist/i18n/localize-manifest.test.d.ts.map +1 -0
  95. package/dist/i18n/localize-manifest.test.js +71 -0
  96. package/dist/messages/catalogs.test.d.ts +2 -0
  97. package/dist/messages/catalogs.test.d.ts.map +1 -0
  98. package/dist/messages/catalogs.test.js +80 -0
  99. package/dist/messages/en/app.d.ts +8 -0
  100. package/dist/messages/en/app.d.ts.map +1 -0
  101. package/dist/messages/en/app.js +7 -0
  102. package/dist/messages/en/blocks.d.ts +54 -0
  103. package/dist/messages/en/blocks.d.ts.map +1 -0
  104. package/dist/messages/en/blocks.js +53 -0
  105. package/dist/messages/en/canvas.d.ts +31 -0
  106. package/dist/messages/en/canvas.d.ts.map +1 -0
  107. package/dist/messages/en/canvas.js +30 -0
  108. package/dist/messages/en/clipboard.d.ts +13 -0
  109. package/dist/messages/en/clipboard.d.ts.map +1 -0
  110. package/dist/messages/en/clipboard.js +12 -0
  111. package/dist/messages/en/colorPicker.d.ts +20 -0
  112. package/dist/messages/en/colorPicker.d.ts.map +1 -0
  113. package/dist/messages/en/colorPicker.js +19 -0
  114. package/dist/messages/en/diagnostics.d.ts +40 -0
  115. package/dist/messages/en/diagnostics.d.ts.map +1 -0
  116. package/dist/messages/en/diagnostics.js +39 -0
  117. package/dist/messages/en/dialogs/common.d.ts +6 -0
  118. package/dist/messages/en/dialogs/common.d.ts.map +1 -0
  119. package/dist/messages/en/dialogs/common.js +5 -0
  120. package/dist/messages/en/dialogs/conflict.d.ts +15 -0
  121. package/dist/messages/en/dialogs/conflict.d.ts.map +1 -0
  122. package/dist/messages/en/dialogs/conflict.js +14 -0
  123. package/dist/messages/en/dialogs/delete.d.ts +19 -0
  124. package/dist/messages/en/dialogs/delete.d.ts.map +1 -0
  125. package/dist/messages/en/dialogs/delete.js +18 -0
  126. package/dist/messages/en/dialogs/pageOptions.d.ts +9 -0
  127. package/dist/messages/en/dialogs/pageOptions.d.ts.map +1 -0
  128. package/dist/messages/en/dialogs/pageOptions.js +8 -0
  129. package/dist/messages/en/dialogs/publish.d.ts +15 -0
  130. package/dist/messages/en/dialogs/publish.d.ts.map +1 -0
  131. package/dist/messages/en/dialogs/publish.js +14 -0
  132. package/dist/messages/en/dnd.d.ts +19 -0
  133. package/dist/messages/en/dnd.d.ts.map +1 -0
  134. package/dist/messages/en/dnd.js +18 -0
  135. package/dist/messages/en/editor.d.ts +30 -0
  136. package/dist/messages/en/editor.d.ts.map +1 -0
  137. package/dist/messages/en/editor.js +29 -0
  138. package/dist/messages/en/external.d.ts +6 -0
  139. package/dist/messages/en/external.d.ts.map +1 -0
  140. package/dist/messages/en/external.js +5 -0
  141. package/dist/messages/en/insert.d.ts +25 -0
  142. package/dist/messages/en/insert.d.ts.map +1 -0
  143. package/dist/messages/en/insert.js +24 -0
  144. package/dist/messages/en/inspector.d.ts +176 -0
  145. package/dist/messages/en/inspector.d.ts.map +1 -0
  146. package/dist/messages/en/inspector.js +175 -0
  147. package/dist/messages/en/issues.d.ts +36 -0
  148. package/dist/messages/en/issues.d.ts.map +1 -0
  149. package/dist/messages/en/issues.js +35 -0
  150. package/dist/messages/en/layers.d.ts +29 -0
  151. package/dist/messages/en/layers.d.ts.map +1 -0
  152. package/dist/messages/en/layers.js +28 -0
  153. package/dist/messages/en/leftPanel.d.ts +15 -0
  154. package/dist/messages/en/leftPanel.d.ts.map +1 -0
  155. package/dist/messages/en/leftPanel.js +14 -0
  156. package/dist/messages/en/list.d.ts +9 -0
  157. package/dist/messages/en/list.d.ts.map +1 -0
  158. package/dist/messages/en/list.js +8 -0
  159. package/dist/messages/en/locale.d.ts +4 -0
  160. package/dist/messages/en/locale.d.ts.map +1 -0
  161. package/dist/messages/en/locale.js +3 -0
  162. package/dist/messages/en/media.d.ts +51 -0
  163. package/dist/messages/en/media.d.ts.map +1 -0
  164. package/dist/messages/en/media.js +50 -0
  165. package/dist/messages/en/menu.d.ts +12 -0
  166. package/dist/messages/en/menu.d.ts.map +1 -0
  167. package/dist/messages/en/menu.js +11 -0
  168. package/dist/messages/en/patterns.d.ts +24 -0
  169. package/dist/messages/en/patterns.d.ts.map +1 -0
  170. package/dist/messages/en/patterns.js +23 -0
  171. package/dist/messages/en/preview.d.ts +8 -0
  172. package/dist/messages/en/preview.d.ts.map +1 -0
  173. package/dist/messages/en/preview.js +7 -0
  174. package/dist/messages/en/publish.d.ts +19 -0
  175. package/dist/messages/en/publish.d.ts.map +1 -0
  176. package/dist/messages/en/publish.js +18 -0
  177. package/dist/messages/en/richText.d.ts +21 -0
  178. package/dist/messages/en/richText.d.ts.map +1 -0
  179. package/dist/messages/en/richText.js +20 -0
  180. package/dist/messages/en/sample.d.ts +5 -0
  181. package/dist/messages/en/sample.d.ts.map +1 -0
  182. package/dist/messages/en/sample.js +4 -0
  183. package/dist/messages/en/save.d.ts +15 -0
  184. package/dist/messages/en/save.d.ts.map +1 -0
  185. package/dist/messages/en/save.js +14 -0
  186. package/dist/messages/en/shortcut.d.ts +36 -0
  187. package/dist/messages/en/shortcut.d.ts.map +1 -0
  188. package/dist/messages/en/shortcut.js +35 -0
  189. package/dist/messages/en/statusBar.d.ts +14 -0
  190. package/dist/messages/en/statusBar.d.ts.map +1 -0
  191. package/dist/messages/en/statusBar.js +13 -0
  192. package/dist/messages/en/structure.d.ts +28 -0
  193. package/dist/messages/en/structure.d.ts.map +1 -0
  194. package/dist/messages/en/structure.js +27 -0
  195. package/dist/messages/en/style.d.ts +168 -0
  196. package/dist/messages/en/style.d.ts.map +1 -0
  197. package/dist/messages/en/style.js +167 -0
  198. package/dist/messages/en/styleField.d.ts +301 -0
  199. package/dist/messages/en/styleField.d.ts.map +1 -0
  200. package/dist/messages/en/styleField.js +300 -0
  201. package/dist/messages/en/styleOption.d.ts +128 -0
  202. package/dist/messages/en/styleOption.d.ts.map +1 -0
  203. package/dist/messages/en/styleOption.js +127 -0
  204. package/dist/messages/en/styleSection.d.ts +16 -0
  205. package/dist/messages/en/styleSection.d.ts.map +1 -0
  206. package/dist/messages/en/styleSection.js +15 -0
  207. package/dist/messages/en/toast.d.ts +22 -0
  208. package/dist/messages/en/toast.d.ts.map +1 -0
  209. package/dist/messages/en/toast.js +21 -0
  210. package/dist/messages/en/toolbar.d.ts +47 -0
  211. package/dist/messages/en/toolbar.d.ts.map +1 -0
  212. package/dist/messages/en/toolbar.js +46 -0
  213. package/dist/messages/en/translation.d.ts +7 -0
  214. package/dist/messages/en/translation.d.ts.map +1 -0
  215. package/dist/messages/en/translation.js +6 -0
  216. package/dist/messages/en/ui.d.ts +4 -0
  217. package/dist/messages/en/ui.d.ts.map +1 -0
  218. package/dist/messages/en/ui.js +3 -0
  219. package/dist/messages/en/values.d.ts +45 -0
  220. package/dist/messages/en/values.d.ts.map +1 -0
  221. package/dist/messages/en/values.js +44 -0
  222. package/dist/messages/en.d.ts +1298 -202
  223. package/dist/messages/en.d.ts.map +1 -1
  224. package/dist/messages/en.js +82 -330
  225. package/dist/messages/index.d.ts +12 -0
  226. package/dist/messages/index.d.ts.map +1 -1
  227. package/dist/messages/index.js +28 -1
  228. package/dist/messages/pl/app.d.ts +8 -0
  229. package/dist/messages/pl/app.d.ts.map +1 -0
  230. package/dist/messages/pl/app.js +7 -0
  231. package/dist/messages/pl/blocks.d.ts +54 -0
  232. package/dist/messages/pl/blocks.d.ts.map +1 -0
  233. package/dist/messages/pl/blocks.js +53 -0
  234. package/dist/messages/pl/canvas.d.ts +31 -0
  235. package/dist/messages/pl/canvas.d.ts.map +1 -0
  236. package/dist/messages/pl/canvas.js +30 -0
  237. package/dist/messages/pl/clipboard.d.ts +13 -0
  238. package/dist/messages/pl/clipboard.d.ts.map +1 -0
  239. package/dist/messages/pl/clipboard.js +12 -0
  240. package/dist/messages/pl/colorPicker.d.ts +20 -0
  241. package/dist/messages/pl/colorPicker.d.ts.map +1 -0
  242. package/dist/messages/pl/colorPicker.js +19 -0
  243. package/dist/messages/pl/componentLabels.d.ts +9 -0
  244. package/dist/messages/pl/componentLabels.d.ts.map +1 -0
  245. package/dist/messages/pl/componentLabels.js +308 -0
  246. package/dist/messages/pl/diagnostics.d.ts +39 -0
  247. package/dist/messages/pl/diagnostics.d.ts.map +1 -0
  248. package/dist/messages/pl/diagnostics.js +38 -0
  249. package/dist/messages/pl/dialogs/common.d.ts +6 -0
  250. package/dist/messages/pl/dialogs/common.d.ts.map +1 -0
  251. package/dist/messages/pl/dialogs/common.js +5 -0
  252. package/dist/messages/pl/dialogs/conflict.d.ts +15 -0
  253. package/dist/messages/pl/dialogs/conflict.d.ts.map +1 -0
  254. package/dist/messages/pl/dialogs/conflict.js +14 -0
  255. package/dist/messages/pl/dialogs/delete.d.ts +19 -0
  256. package/dist/messages/pl/dialogs/delete.d.ts.map +1 -0
  257. package/dist/messages/pl/dialogs/delete.js +18 -0
  258. package/dist/messages/pl/dialogs/pageOptions.d.ts +9 -0
  259. package/dist/messages/pl/dialogs/pageOptions.d.ts.map +1 -0
  260. package/dist/messages/pl/dialogs/pageOptions.js +8 -0
  261. package/dist/messages/pl/dialogs/publish.d.ts +15 -0
  262. package/dist/messages/pl/dialogs/publish.d.ts.map +1 -0
  263. package/dist/messages/pl/dialogs/publish.js +14 -0
  264. package/dist/messages/pl/dnd.d.ts +19 -0
  265. package/dist/messages/pl/dnd.d.ts.map +1 -0
  266. package/dist/messages/pl/dnd.js +18 -0
  267. package/dist/messages/pl/editor.d.ts +30 -0
  268. package/dist/messages/pl/editor.d.ts.map +1 -0
  269. package/dist/messages/pl/editor.js +29 -0
  270. package/dist/messages/pl/external.d.ts +6 -0
  271. package/dist/messages/pl/external.d.ts.map +1 -0
  272. package/dist/messages/pl/external.js +5 -0
  273. package/dist/messages/pl/insert.d.ts +25 -0
  274. package/dist/messages/pl/insert.d.ts.map +1 -0
  275. package/dist/messages/pl/insert.js +24 -0
  276. package/dist/messages/pl/inspector.d.ts +176 -0
  277. package/dist/messages/pl/inspector.d.ts.map +1 -0
  278. package/dist/messages/pl/inspector.js +175 -0
  279. package/dist/messages/pl/issues.d.ts +36 -0
  280. package/dist/messages/pl/issues.d.ts.map +1 -0
  281. package/dist/messages/pl/issues.js +35 -0
  282. package/dist/messages/pl/layers.d.ts +29 -0
  283. package/dist/messages/pl/layers.d.ts.map +1 -0
  284. package/dist/messages/pl/layers.js +28 -0
  285. package/dist/messages/pl/leftPanel.d.ts +15 -0
  286. package/dist/messages/pl/leftPanel.d.ts.map +1 -0
  287. package/dist/messages/pl/leftPanel.js +14 -0
  288. package/dist/messages/pl/list.d.ts +9 -0
  289. package/dist/messages/pl/list.d.ts.map +1 -0
  290. package/dist/messages/pl/list.js +8 -0
  291. package/dist/messages/pl/locale.d.ts +4 -0
  292. package/dist/messages/pl/locale.d.ts.map +1 -0
  293. package/dist/messages/pl/locale.js +3 -0
  294. package/dist/messages/pl/media.d.ts +51 -0
  295. package/dist/messages/pl/media.d.ts.map +1 -0
  296. package/dist/messages/pl/media.js +50 -0
  297. package/dist/messages/pl/menu.d.ts +12 -0
  298. package/dist/messages/pl/menu.d.ts.map +1 -0
  299. package/dist/messages/pl/menu.js +11 -0
  300. package/dist/messages/pl/patterns.d.ts +24 -0
  301. package/dist/messages/pl/patterns.d.ts.map +1 -0
  302. package/dist/messages/pl/patterns.js +23 -0
  303. package/dist/messages/pl/preview.d.ts +8 -0
  304. package/dist/messages/pl/preview.d.ts.map +1 -0
  305. package/dist/messages/pl/preview.js +7 -0
  306. package/dist/messages/pl/publish.d.ts +19 -0
  307. package/dist/messages/pl/publish.d.ts.map +1 -0
  308. package/dist/messages/pl/publish.js +18 -0
  309. package/dist/messages/pl/richText.d.ts +21 -0
  310. package/dist/messages/pl/richText.d.ts.map +1 -0
  311. package/dist/messages/pl/richText.js +20 -0
  312. package/dist/messages/pl/sample.d.ts +5 -0
  313. package/dist/messages/pl/sample.d.ts.map +1 -0
  314. package/dist/messages/pl/sample.js +4 -0
  315. package/dist/messages/pl/save.d.ts +15 -0
  316. package/dist/messages/pl/save.d.ts.map +1 -0
  317. package/dist/messages/pl/save.js +14 -0
  318. package/dist/messages/pl/shortcut.d.ts +36 -0
  319. package/dist/messages/pl/shortcut.d.ts.map +1 -0
  320. package/dist/messages/pl/shortcut.js +35 -0
  321. package/dist/messages/pl/statusBar.d.ts +14 -0
  322. package/dist/messages/pl/statusBar.d.ts.map +1 -0
  323. package/dist/messages/pl/statusBar.js +13 -0
  324. package/dist/messages/pl/structure.d.ts +28 -0
  325. package/dist/messages/pl/structure.d.ts.map +1 -0
  326. package/dist/messages/pl/structure.js +27 -0
  327. package/dist/messages/pl/style.d.ts +168 -0
  328. package/dist/messages/pl/style.d.ts.map +1 -0
  329. package/dist/messages/pl/style.js +167 -0
  330. package/dist/messages/pl/styleField.d.ts +301 -0
  331. package/dist/messages/pl/styleField.d.ts.map +1 -0
  332. package/dist/messages/pl/styleField.js +300 -0
  333. package/dist/messages/pl/styleOption.d.ts +128 -0
  334. package/dist/messages/pl/styleOption.d.ts.map +1 -0
  335. package/dist/messages/pl/styleOption.js +127 -0
  336. package/dist/messages/pl/styleSection.d.ts +16 -0
  337. package/dist/messages/pl/styleSection.d.ts.map +1 -0
  338. package/dist/messages/pl/styleSection.js +15 -0
  339. package/dist/messages/pl/toast.d.ts +22 -0
  340. package/dist/messages/pl/toast.d.ts.map +1 -0
  341. package/dist/messages/pl/toast.js +21 -0
  342. package/dist/messages/pl/toolbar.d.ts +47 -0
  343. package/dist/messages/pl/toolbar.d.ts.map +1 -0
  344. package/dist/messages/pl/toolbar.js +46 -0
  345. package/dist/messages/pl/translation.d.ts +7 -0
  346. package/dist/messages/pl/translation.d.ts.map +1 -0
  347. package/dist/messages/pl/translation.js +6 -0
  348. package/dist/messages/pl/ui.d.ts +4 -0
  349. package/dist/messages/pl/ui.d.ts.map +1 -0
  350. package/dist/messages/pl/ui.js +3 -0
  351. package/dist/messages/pl/values.d.ts +45 -0
  352. package/dist/messages/pl/values.d.ts.map +1 -0
  353. package/dist/messages/pl/values.js +44 -0
  354. package/dist/messages/pl.d.ts.map +1 -1
  355. package/dist/messages/pl.js +82 -325
  356. package/dist/messages/plural.test.d.ts +2 -0
  357. package/dist/messages/plural.test.d.ts.map +1 -0
  358. package/dist/messages/plural.test.js +50 -0
  359. package/dist/panels/breadcrumbs/breadcrumbs.d.ts +1 -1
  360. package/dist/panels/breadcrumbs/breadcrumbs.d.ts.map +1 -1
  361. package/dist/panels/breadcrumbs/breadcrumbs.js +10 -3
  362. package/dist/panels/breadcrumbs/breadcrumbs.test.js +9 -2
  363. package/dist/panels/index.d.ts +3 -0
  364. package/dist/panels/index.d.ts.map +1 -1
  365. package/dist/panels/index.js +1 -0
  366. package/dist/panels/insert/catalog.d.ts +21 -1
  367. package/dist/panels/insert/catalog.d.ts.map +1 -1
  368. package/dist/panels/insert/catalog.js +85 -3
  369. package/dist/panels/insert/catalog.order.test.js +106 -1
  370. package/dist/panels/insert/index.d.ts +1 -0
  371. package/dist/panels/insert/index.d.ts.map +1 -1
  372. package/dist/panels/insert/insert-panel.d.ts +14 -4
  373. package/dist/panels/insert/insert-panel.d.ts.map +1 -1
  374. package/dist/panels/insert/insert-panel.js +128 -69
  375. package/dist/panels/insert/insert-panel.test.js +278 -37
  376. package/dist/panels/insert/target.d.ts +5 -1
  377. package/dist/panels/insert/target.d.ts.map +1 -1
  378. package/dist/panels/insert/target.js +11 -1
  379. package/dist/panels/inspector/author-fields.d.ts +21 -0
  380. package/dist/panels/inspector/author-fields.d.ts.map +1 -0
  381. package/dist/panels/inspector/author-fields.js +191 -0
  382. package/dist/panels/inspector/author-fields.test.d.ts +2 -0
  383. package/dist/panels/inspector/author-fields.test.d.ts.map +1 -0
  384. package/dist/panels/inspector/author-fields.test.js +237 -0
  385. package/dist/panels/inspector/controls/external-link.d.ts +24 -0
  386. package/dist/panels/inspector/controls/external-link.d.ts.map +1 -0
  387. package/dist/panels/inspector/controls/external-link.js +43 -0
  388. package/dist/panels/inspector/controls/external-link.test.d.ts +2 -0
  389. package/dist/panels/inspector/controls/external-link.test.d.ts.map +1 -0
  390. package/dist/panels/inspector/controls/external-link.test.js +105 -0
  391. package/dist/panels/inspector/controls/index.d.ts +1 -0
  392. package/dist/panels/inspector/controls/index.d.ts.map +1 -1
  393. package/dist/panels/inspector/controls/index.js +1 -0
  394. package/dist/panels/inspector/controls/media.d.ts +3 -1
  395. package/dist/panels/inspector/controls/media.d.ts.map +1 -1
  396. package/dist/panels/inspector/controls/media.js +8 -3
  397. package/dist/panels/inspector/controls/rich-text.d.ts.map +1 -1
  398. package/dist/panels/inspector/controls/rich-text.js +36 -6
  399. package/dist/panels/inspector/controls/textarea.d.ts +7 -2
  400. package/dist/panels/inspector/controls/textarea.d.ts.map +1 -1
  401. package/dist/panels/inspector/controls/textarea.js +37 -2
  402. package/dist/panels/inspector/default-hint.d.ts +13 -0
  403. package/dist/panels/inspector/default-hint.d.ts.map +1 -0
  404. package/dist/panels/inspector/default-hint.js +30 -0
  405. package/dist/panels/inspector/default-hint.test.d.ts +2 -0
  406. package/dist/panels/inspector/default-hint.test.d.ts.map +1 -0
  407. package/dist/panels/inspector/default-hint.test.js +46 -0
  408. package/dist/panels/inspector/index.d.ts +3 -3
  409. package/dist/panels/inspector/index.d.ts.map +1 -1
  410. package/dist/panels/inspector/index.js +2 -2
  411. package/dist/panels/inspector/inspector.d.ts +20 -2
  412. package/dist/panels/inspector/inspector.d.ts.map +1 -1
  413. package/dist/panels/inspector/inspector.js +246 -26
  414. package/dist/panels/inspector/inspector.test.js +276 -11
  415. package/dist/panels/inspector/props-panel.d.ts +36 -0
  416. package/dist/panels/inspector/props-panel.d.ts.map +1 -1
  417. package/dist/panels/inspector/props-panel.js +99 -17
  418. package/dist/panels/inspector/props-panel.test.d.ts +2 -0
  419. package/dist/panels/inspector/props-panel.test.d.ts.map +1 -0
  420. package/dist/panels/inspector/props-panel.test.js +17 -0
  421. package/dist/panels/inspector/scrub-label.d.ts +14 -0
  422. package/dist/panels/inspector/scrub-label.d.ts.map +1 -0
  423. package/dist/panels/inspector/scrub-label.js +75 -0
  424. package/dist/panels/inspector/scrub-label.test.d.ts +2 -0
  425. package/dist/panels/inspector/scrub-label.test.d.ts.map +1 -0
  426. package/dist/panels/inspector/scrub-label.test.js +132 -0
  427. package/dist/panels/inspector/styles/background-media.d.ts +28 -0
  428. package/dist/panels/inspector/styles/background-media.d.ts.map +1 -0
  429. package/dist/panels/inspector/styles/background-media.js +78 -0
  430. package/dist/panels/inspector/styles/box-model.d.ts +13 -16
  431. package/dist/panels/inspector/styles/box-model.d.ts.map +1 -1
  432. package/dist/panels/inspector/styles/box-model.js +10 -25
  433. package/dist/panels/inspector/styles/color-input.d.ts +3 -0
  434. package/dist/panels/inspector/styles/color-input.d.ts.map +1 -0
  435. package/dist/panels/inspector/styles/color-input.js +72 -0
  436. package/dist/panels/inspector/styles/gradient-fields.d.ts +9 -0
  437. package/dist/panels/inspector/styles/gradient-fields.d.ts.map +1 -0
  438. package/dist/panels/inspector/styles/gradient-fields.js +50 -0
  439. package/dist/panels/inspector/styles/index.d.ts +2 -0
  440. package/dist/panels/inspector/styles/index.d.ts.map +1 -1
  441. package/dist/panels/inspector/styles/index.js +2 -0
  442. package/dist/panels/inspector/styles/model.d.ts +27 -5
  443. package/dist/panels/inspector/styles/model.d.ts.map +1 -1
  444. package/dist/panels/inspector/styles/model.js +101 -3
  445. package/dist/panels/inspector/styles/motion-rows.d.ts +17 -0
  446. package/dist/panels/inspector/styles/motion-rows.d.ts.map +1 -0
  447. package/dist/panels/inspector/styles/motion-rows.js +117 -0
  448. package/dist/panels/inspector/styles/number-input.d.ts +4 -0
  449. package/dist/panels/inspector/styles/number-input.d.ts.map +1 -0
  450. package/dist/panels/inspector/styles/number-input.js +12 -0
  451. package/dist/panels/inspector/styles/option-label.d.ts +7 -0
  452. package/dist/panels/inspector/styles/option-label.d.ts.map +1 -0
  453. package/dist/panels/inspector/styles/option-label.js +9 -0
  454. package/dist/panels/inspector/styles/property-label.d.ts +9 -0
  455. package/dist/panels/inspector/styles/property-label.d.ts.map +1 -0
  456. package/dist/panels/inspector/styles/property-label.js +11 -0
  457. package/dist/panels/inspector/styles/section-state.d.ts +22 -0
  458. package/dist/panels/inspector/styles/section-state.d.ts.map +1 -0
  459. package/dist/panels/inspector/styles/section-state.js +96 -0
  460. package/dist/panels/inspector/styles/section.d.ts +25 -0
  461. package/dist/panels/inspector/styles/section.d.ts.map +1 -0
  462. package/dist/panels/inspector/styles/section.js +43 -0
  463. package/dist/panels/inspector/styles/sections-context.d.ts +13 -0
  464. package/dist/panels/inspector/styles/sections-context.d.ts.map +1 -0
  465. package/dist/panels/inspector/styles/sections-context.js +19 -0
  466. package/dist/panels/inspector/styles/sections-context.test.d.ts +2 -0
  467. package/dist/panels/inspector/styles/sections-context.test.d.ts.map +1 -0
  468. package/dist/panels/inspector/styles/sections-context.test.js +18 -0
  469. package/dist/panels/inspector/styles/sections-toggle.d.ts +6 -0
  470. package/dist/panels/inspector/styles/sections-toggle.d.ts.map +1 -0
  471. package/dist/panels/inspector/styles/sections-toggle.js +18 -0
  472. package/dist/panels/inspector/styles/segments.d.ts +3 -0
  473. package/dist/panels/inspector/styles/segments.d.ts.map +1 -1
  474. package/dist/panels/inspector/styles/segments.js +11 -4
  475. package/dist/panels/inspector/styles/sides-editor.d.ts +1 -1
  476. package/dist/panels/inspector/styles/sides-editor.d.ts.map +1 -1
  477. package/dist/panels/inspector/styles/sides-editor.js +33 -4
  478. package/dist/panels/inspector/styles/style-inspector.d.ts +3 -1
  479. package/dist/panels/inspector/styles/style-inspector.d.ts.map +1 -1
  480. package/dist/panels/inspector/styles/style-inspector.js +610 -42
  481. package/dist/panels/inspector/styles/style-inspector.test.js +694 -14
  482. package/dist/panels/inspector/styles/token-picker.d.ts +1 -1
  483. package/dist/panels/inspector/styles/token-picker.d.ts.map +1 -1
  484. package/dist/panels/inspector/styles/token-picker.js +10 -3
  485. package/dist/panels/inspector/styles/widgets.d.ts +116 -0
  486. package/dist/panels/inspector/styles/widgets.d.ts.map +1 -0
  487. package/dist/panels/inspector/styles/widgets.js +304 -0
  488. package/dist/panels/inspector/styles/widgets.test.d.ts +2 -0
  489. package/dist/panels/inspector/styles/widgets.test.d.ts.map +1 -0
  490. package/dist/panels/inspector/styles/widgets.test.js +247 -0
  491. package/dist/panels/inspector/values/value-editor.d.ts +1 -1
  492. package/dist/panels/inspector/values/value-editor.d.ts.map +1 -1
  493. package/dist/panels/inspector/values/value-editor.js +9 -8
  494. package/dist/panels/inspector/values/values.test.js +9 -3
  495. package/dist/panels/issues/collect.d.ts +2 -0
  496. package/dist/panels/issues/collect.d.ts.map +1 -1
  497. package/dist/panels/issues/collect.js +1 -0
  498. package/dist/panels/issues/index.d.ts +1 -0
  499. package/dist/panels/issues/index.d.ts.map +1 -1
  500. package/dist/panels/issues/index.js +1 -0
  501. package/dist/panels/issues/issues-panel.d.ts +4 -3
  502. package/dist/panels/issues/issues-panel.d.ts.map +1 -1
  503. package/dist/panels/issues/issues-panel.js +22 -35
  504. package/dist/panels/issues/path.d.ts +7 -0
  505. package/dist/panels/issues/path.d.ts.map +1 -0
  506. package/dist/panels/issues/path.js +21 -0
  507. package/dist/panels/layers/flatten.d.ts +16 -2
  508. package/dist/panels/layers/flatten.d.ts.map +1 -1
  509. package/dist/panels/layers/flatten.js +48 -4
  510. package/dist/panels/layers/layers-panel.d.ts +5 -2
  511. package/dist/panels/layers/layers-panel.d.ts.map +1 -1
  512. package/dist/panels/layers/layers-panel.js +177 -35
  513. package/dist/panels/layers/layers-panel.test.js +173 -15
  514. package/dist/panels/left-panel.d.ts +17 -0
  515. package/dist/panels/left-panel.d.ts.map +1 -0
  516. package/dist/panels/left-panel.js +47 -0
  517. package/dist/panels/left-panel.test.d.ts +2 -0
  518. package/dist/panels/left-panel.test.d.ts.map +1 -0
  519. package/dist/panels/left-panel.test.js +77 -0
  520. package/dist/persistence/persistence.test.js +9 -3
  521. package/dist/persistence/react.d.ts.map +1 -1
  522. package/dist/persistence/react.js +2 -2
  523. package/dist/preview/preview.d.ts +8 -0
  524. package/dist/preview/preview.d.ts.map +1 -1
  525. package/dist/preview/preview.js +21 -1
  526. package/dist/preview/preview.test.js +18 -1
  527. package/dist/shortcuts/actions.d.ts +13 -2
  528. package/dist/shortcuts/actions.d.ts.map +1 -1
  529. package/dist/shortcuts/actions.js +70 -15
  530. package/dist/shortcuts/help.d.ts +11 -0
  531. package/dist/shortcuts/help.d.ts.map +1 -0
  532. package/dist/shortcuts/help.js +77 -0
  533. package/dist/shortcuts/index.d.ts +5 -2
  534. package/dist/shortcuts/index.d.ts.map +1 -1
  535. package/dist/shortcuts/index.js +3 -1
  536. package/dist/shortcuts/map.d.ts +1 -1
  537. package/dist/shortcuts/map.d.ts.map +1 -1
  538. package/dist/shortcuts/map.js +14 -8
  539. package/dist/shortcuts/navigation.d.ts +13 -0
  540. package/dist/shortcuts/navigation.d.ts.map +1 -0
  541. package/dist/shortcuts/navigation.js +48 -0
  542. package/dist/shortcuts/shortcuts.d.ts +12 -1
  543. package/dist/shortcuts/shortcuts.d.ts.map +1 -1
  544. package/dist/shortcuts/shortcuts.js +61 -14
  545. package/dist/shortcuts/shortcuts.test.js +206 -5
  546. package/dist/store/create-store.d.ts.map +1 -1
  547. package/dist/store/create-store.js +19 -1
  548. package/dist/store/index.d.ts +4 -1
  549. package/dist/store/index.d.ts.map +1 -1
  550. package/dist/store/index.js +3 -1
  551. package/dist/store/react.d.ts +4 -0
  552. package/dist/store/react.d.ts.map +1 -1
  553. package/dist/store/react.js +7 -0
  554. package/dist/store/store.test.js +24 -0
  555. package/dist/store/structure-lock.d.ts +16 -0
  556. package/dist/store/structure-lock.d.ts.map +1 -0
  557. package/dist/store/structure-lock.js +43 -0
  558. package/dist/store/structure-lock.test.d.ts +2 -0
  559. package/dist/store/structure-lock.test.d.ts.map +1 -0
  560. package/dist/store/structure-lock.test.js +49 -0
  561. package/dist/store/types.d.ts +9 -0
  562. package/dist/store/types.d.ts.map +1 -1
  563. package/dist/store/view.d.ts +20 -0
  564. package/dist/store/view.d.ts.map +1 -0
  565. package/dist/store/view.js +17 -0
  566. package/dist/store/view.test.d.ts +2 -0
  567. package/dist/store/view.test.d.ts.map +1 -0
  568. package/dist/store/view.test.js +103 -0
  569. package/dist/styles/tokens.test.js +88 -9
  570. package/dist/styles.css +4112 -586
  571. package/dist/toolbar/brand.d.ts +2 -2
  572. package/dist/toolbar/brand.d.ts.map +1 -1
  573. package/dist/toolbar/brand.js +4 -4
  574. package/dist/toolbar/breakpoint-control.d.ts +4 -0
  575. package/dist/toolbar/breakpoint-control.d.ts.map +1 -1
  576. package/dist/toolbar/breakpoint-control.js +11 -4
  577. package/dist/toolbar/editable-title.d.ts +4 -1
  578. package/dist/toolbar/editable-title.d.ts.map +1 -1
  579. package/dist/toolbar/editable-title.js +2 -2
  580. package/dist/toolbar/editable-title.test.js +10 -0
  581. package/dist/toolbar/locale-chip.d.ts +10 -0
  582. package/dist/toolbar/locale-chip.d.ts.map +1 -0
  583. package/dist/toolbar/locale-chip.js +27 -0
  584. package/dist/toolbar/locale-switcher.d.ts.map +1 -1
  585. package/dist/toolbar/locale-switcher.js +4 -1
  586. package/dist/toolbar/more-menu.d.ts +26 -4
  587. package/dist/toolbar/more-menu.d.ts.map +1 -1
  588. package/dist/toolbar/more-menu.js +60 -13
  589. package/dist/toolbar/page-chip.d.ts +10 -0
  590. package/dist/toolbar/page-chip.d.ts.map +1 -0
  591. package/dist/toolbar/page-chip.js +12 -0
  592. package/dist/toolbar/page-options-dialog.d.ts +16 -0
  593. package/dist/toolbar/page-options-dialog.d.ts.map +1 -0
  594. package/dist/toolbar/page-options-dialog.js +13 -0
  595. package/dist/toolbar/panel-toggles.d.ts +3 -2
  596. package/dist/toolbar/panel-toggles.d.ts.map +1 -1
  597. package/dist/toolbar/panel-toggles.js +9 -4
  598. package/dist/toolbar/publish-dialog.d.ts +3 -0
  599. package/dist/toolbar/publish-dialog.d.ts.map +1 -1
  600. package/dist/toolbar/publish-dialog.js +34 -7
  601. package/dist/toolbar/publish.test.js +63 -19
  602. package/dist/toolbar/safe-history.d.ts +3 -0
  603. package/dist/toolbar/safe-history.d.ts.map +1 -0
  604. package/dist/toolbar/safe-history.js +5 -0
  605. package/dist/toolbar/sample-picker.d.ts +24 -4
  606. package/dist/toolbar/sample-picker.d.ts.map +1 -1
  607. package/dist/toolbar/sample-picker.js +42 -18
  608. package/dist/toolbar/toolbar-centre.d.ts +3 -11
  609. package/dist/toolbar/toolbar-centre.d.ts.map +1 -1
  610. package/dist/toolbar/toolbar-centre.js +4 -5
  611. package/dist/toolbar/toolbar-left.d.ts +4 -7
  612. package/dist/toolbar/toolbar-left.d.ts.map +1 -1
  613. package/dist/toolbar/toolbar-left.js +13 -11
  614. package/dist/toolbar/toolbar-right.d.ts +21 -6
  615. package/dist/toolbar/toolbar-right.d.ts.map +1 -1
  616. package/dist/toolbar/toolbar-right.js +28 -14
  617. package/dist/toolbar/toolbar.d.ts +23 -17
  618. package/dist/toolbar/toolbar.d.ts.map +1 -1
  619. package/dist/toolbar/toolbar.js +28 -11
  620. package/dist/toolbar/toolbar.test.js +238 -23
  621. package/dist/toolbar/use-overflow-level.d.ts +2 -1
  622. package/dist/toolbar/use-overflow-level.d.ts.map +1 -1
  623. package/dist/toolbar/use-overflow-level.js +9 -3
  624. package/dist/toolbar/zoom-menu.d.ts +5 -1
  625. package/dist/toolbar/zoom-menu.d.ts.map +1 -1
  626. package/dist/toolbar/zoom-menu.js +3 -2
  627. package/dist/ui/icon.d.ts +53 -0
  628. package/dist/ui/icon.d.ts.map +1 -1
  629. package/dist/ui/icon.js +58 -1
  630. package/dist/ui/icon.test.js +101 -3
  631. package/dist/ui/index.d.ts +4 -3
  632. package/dist/ui/index.d.ts.map +1 -1
  633. package/dist/ui/index.js +3 -2
  634. package/dist/ui/primitives.d.ts +97 -14
  635. package/dist/ui/primitives.d.ts.map +1 -1
  636. package/dist/ui/primitives.js +108 -22
  637. package/dist/ui/primitives.test.js +204 -3
  638. package/dist/ui/structure-locked.d.ts +9 -0
  639. package/dist/ui/structure-locked.d.ts.map +1 -0
  640. package/dist/ui/structure-locked.js +28 -0
  641. package/dist/ui/toast.d.ts +3 -1
  642. package/dist/ui/toast.d.ts.map +1 -1
  643. package/dist/ui/toast.js +21 -5
  644. package/dist/ui/toast.test.js +34 -0
  645. package/package.json +6 -4
@@ -1,16 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // @vitest-environment jsdom
3
3
  import { createRegistryMeta, createSeededIdGenerator, p, s, toManifest, } from '@next-buildr/core';
4
+ import { $getRoot } from 'lexical';
4
5
  import { act } from 'react';
5
6
  import { createRoot } from 'react-dom/client';
6
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
7
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
7
8
  import { axe } from 'vitest-axe';
8
9
  import * as matchers from 'vitest-axe/matchers';
9
10
  import { ManifestProvider } from '../../app/manifest.js';
10
11
  import { MessagesProvider } from '../../messages/index.js';
11
12
  import { createEditorStore, EditorStoreProvider } from '../../store/index.js';
12
13
  import { parseNumber } from './controls/index.js';
13
- import { Inspector } from './inspector.js';
14
+ import { Inspector, InspectorRail } from './inspector.js';
14
15
  import { isAdvancedProp, propLabel } from './props-panel.js';
15
16
  import { readProp } from './value.js';
16
17
  expect.extend(matchers);
@@ -30,6 +31,7 @@ const widget = {
30
31
  symbol: p.icon({}),
31
32
  ariaLabel: p.text({ group: 'accessibility' }),
32
33
  fixed: p.number({ default: 1, localizable: false }),
34
+ rich: p.richText({ label: 'Rich text' }),
33
35
  },
34
36
  contentCategories: ['flow'],
35
37
  styles: { groups: [] },
@@ -75,16 +77,19 @@ afterEach(() => {
75
77
  act(() => root.unmount());
76
78
  document.body.innerHTML = '';
77
79
  });
78
- async function mount(select, extra = {}, doc = fixture()) {
80
+ async function mount(select, extra = {}, doc = fixture(), customMeta) {
81
+ const currentRegistry = customMeta
82
+ ? createRegistryMeta({ components: [page, customMeta] })
83
+ : registry;
79
84
  const store = createEditorStore({
80
85
  doc,
81
- registry,
86
+ registry: currentRegistry,
82
87
  generateId: createSeededIdGenerator(3),
83
88
  validationDelayMs: null,
84
89
  });
85
90
  if (select !== null)
86
91
  store.select(select);
87
- await act(async () => root.render(_jsx(MessagesProvider, { locale: "en", children: _jsx(ManifestProvider, { manifest: manifest, children: _jsx(EditorStoreProvider, { store: store, children: _jsx(Inspector, { ...extra }) }) }) })));
92
+ await act(async () => root.render(_jsx(MessagesProvider, { locale: "en", children: _jsx(ManifestProvider, { manifest: customMeta ? toManifest(currentRegistry) : manifest, children: _jsx(EditorStoreProvider, { store: store, children: _jsx(Inspector, { ...extra }) }) }) })));
88
93
  return store;
89
94
  }
90
95
  const field = (prop) => container.querySelector(`[data-prop=${prop}]`);
@@ -157,13 +162,99 @@ describe('Inspector', () => {
157
162
  expect(toggle().getAttribute('aria-expanded')).toBe('false');
158
163
  window.localStorage.clear();
159
164
  });
160
- it('duplicates and deletes from the header with the same commands as the layers', async () => {
165
+ const openMenu = async () => {
166
+ const trigger = container.querySelector('button[aria-label="More block options"]');
167
+ await act(async () => {
168
+ trigger.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true, button: 0 }));
169
+ trigger.click();
170
+ });
171
+ };
172
+ const menuItem = (label) => [...document.querySelectorAll('[role=menuitem]')].find((el) => el.textContent === label);
173
+ it('duplicates and deletes from the more menu with the same commands as the layers', async () => {
161
174
  const store = await mount('widget0001');
162
- const named = (label) => container.querySelector(`button[aria-label="${label}"]`);
163
- await act(async () => named('Duplicate element').click());
175
+ await openMenu();
176
+ await act(async () => menuItem('Duplicate').click());
164
177
  expect(Object.keys(store.getState().doc.nodes)).toHaveLength(4);
165
- await act(async () => named('Delete element').click());
178
+ await openMenu();
179
+ await act(async () => menuItem('Delete block').click());
166
180
  expect(Object.keys(store.getState().doc.nodes)).toHaveLength(3);
181
+ await act(async () => store.undo());
182
+ expect(Object.keys(store.getState().doc.nodes)).toHaveLength(4);
183
+ });
184
+ it('navigates the more menu with the arrow keys', async () => {
185
+ await mount('widget0001');
186
+ await openMenu();
187
+ const items = () => [...document.querySelectorAll('[role=menuitem]')];
188
+ const key = (k) => act(async () => {
189
+ document.activeElement.dispatchEvent(new KeyboardEvent('keydown', { key: k, bubbles: true, cancelable: true }));
190
+ });
191
+ expect(items().length).toBeGreaterThanOrEqual(2);
192
+ expect(document.activeElement).toBe(items()[0]);
193
+ await key('ArrowDown');
194
+ expect(document.activeElement).toBe(items()[1]);
195
+ await key('End');
196
+ expect(document.activeElement).toBe(items().at(-1));
197
+ await key('ArrowDown');
198
+ expect(document.activeElement).toBe(items()[0]);
199
+ await key('ArrowUp');
200
+ expect(document.activeElement).toBe(items().at(-1));
201
+ await key('Home');
202
+ expect(document.activeElement).toBe(items()[0]);
203
+ await key('Escape');
204
+ expect(document.querySelector('[role=menu]')).toBeNull();
205
+ expect(document.activeElement).toBe(container.querySelector('button[aria-label="More block options"]'));
206
+ });
207
+ it('does not report no match on the Advanced tab while its name field matches', async () => {
208
+ await mount('widget0001');
209
+ await openTab('Advanced');
210
+ const search = container.querySelector('.bd-inspector-search input');
211
+ await typeInto(search, 'name');
212
+ expect(container.querySelector('[data-attr=name]')).not.toBeNull();
213
+ expect(container.querySelector('[data-state=no-match]')).toBeNull();
214
+ await typeInto(search, 'zzz');
215
+ expect(container.querySelector('[data-attr=name]')).toBeNull();
216
+ expect(container.querySelector('[data-state=no-match]')).not.toBeNull();
217
+ });
218
+ it('shows an excerpt of the text in the subtitle', async () => {
219
+ await mount('widget0001');
220
+ expect(container.querySelector('.bd-inspector-subtitle')?.textContent).toContain('Widget · “Hello”');
221
+ });
222
+ it('keeps its own tab, or follows a controlled one', async () => {
223
+ await mount('widget0001');
224
+ const tab = (name) => [...container.querySelectorAll('[role=tab]')].find((el) => el.textContent?.includes(name));
225
+ await act(async () => {
226
+ tab('Advanced').dispatchEvent(new MouseEvent('mousedown', { bubbles: true, button: 0 }));
227
+ });
228
+ expect(tab('Advanced').getAttribute('aria-selected')).toBe('true');
229
+ await act(async () => root.unmount());
230
+ root = createRoot(container);
231
+ const onTabChange = vi.fn();
232
+ await mount('widget0001', { tab: 'style', onTabChange });
233
+ expect(tab('Style').getAttribute('aria-selected')).toBe('true');
234
+ await act(async () => {
235
+ tab('Content').dispatchEvent(new MouseEvent('mousedown', { bubbles: true, button: 0 }));
236
+ });
237
+ expect(onTabChange).toHaveBeenCalledWith('content');
238
+ expect(tab('Style').getAttribute('aria-selected')).toBe('true');
239
+ });
240
+ it('shows the page settings action in the empty state only when given', async () => {
241
+ await mount(null);
242
+ expect(container.textContent).not.toContain('Page settings');
243
+ await act(async () => root.unmount());
244
+ root = createRoot(container);
245
+ const onPageSettings = vi.fn();
246
+ await mount(null, { onPageSettings });
247
+ await act(async () => [...container.querySelectorAll('button')].find((b) => b.textContent === 'Page settings').click());
248
+ expect(onPageSettings).toHaveBeenCalled();
249
+ });
250
+ it('renders the rail and reports tab and expand clicks', async () => {
251
+ const onTabChange = vi.fn();
252
+ const onExpand = vi.fn();
253
+ await act(async () => root.render(_jsx(MessagesProvider, { locale: "en", children: _jsx(InspectorRail, { tab: "content", onTabChange: onTabChange, onExpand: onExpand }) })));
254
+ const style = container.querySelector('button[aria-label="Style"]');
255
+ await act(async () => style.click());
256
+ expect(onTabChange).toHaveBeenCalledWith('style');
257
+ expect(onExpand).toHaveBeenCalled();
167
258
  });
168
259
  it('gives every control an accessible name and passes axe', async () => {
169
260
  await mount('widget0001');
@@ -256,8 +347,17 @@ describe('Inspector', () => {
256
347
  };
257
348
  await mount('widget0001', {}, bound);
258
349
  expect(field('title').querySelector('input').value).toBe('post.title');
259
- expect(field('title').querySelector('[aria-pressed=true]')?.textContent).toBe('Data');
260
- expect(field('href').querySelector('[aria-pressed=true]')?.textContent).toBe('Formula');
350
+ await act(async () => {
351
+ field('title').querySelector('.bd-value-modes button').click();
352
+ });
353
+ expect(document.querySelector('.bd-popover [aria-pressed=true]')?.getAttribute('aria-label')).toBe('Data');
354
+ await act(async () => {
355
+ document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
356
+ });
357
+ await act(async () => {
358
+ field('href').querySelector('.bd-value-modes button').click();
359
+ });
360
+ expect(document.querySelector('.bd-popover [aria-pressed=true]')?.getAttribute('aria-label')).toBe('Formula');
261
361
  expect(field('href').querySelector('textarea').value).toBe('post.slug');
262
362
  });
263
363
  it('writes a translation to the language being edited, only for translatable props', async () => {
@@ -326,3 +426,168 @@ describe('Inspector', () => {
326
426
  expect(container.textContent).toContain('styles of widget0001');
327
427
  });
328
428
  });
429
+ describe('template v2 prop controls', () => {
430
+ it('scrubs bounded numeric props through node.setProp with undo and redo', async () => {
431
+ const store = await mount('widget0001');
432
+ const dispatch = vi.spyOn(store, 'dispatch');
433
+ const label = field('count').querySelector('label');
434
+ const drag = async (x) => act(async () => {
435
+ label.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true, button: 0, clientX: 0 }));
436
+ label.dispatchEvent(new MouseEvent('pointermove', { bubbles: true, clientX: x }));
437
+ label.dispatchEvent(new MouseEvent('pointerup', { bubbles: true }));
438
+ });
439
+ await drag(6);
440
+ expect(propOf(store, 'widget0001', 'count')).toEqual({ kind: 'static', value: 7 });
441
+ expect(dispatch).toHaveBeenCalledWith({
442
+ type: 'node.setProp',
443
+ payload: { id: 'widget0001', prop: 'count', value: { kind: 'static', value: 7 } },
444
+ });
445
+ await drag(90);
446
+ expect(propOf(store, 'widget0001', 'count')).toEqual({ kind: 'static', value: 10 });
447
+ await act(async () => {
448
+ store.undo();
449
+ });
450
+ expect(propOf(store, 'widget0001', 'count')).toEqual({ kind: 'static', value: 7 });
451
+ await act(async () => {
452
+ store.redo();
453
+ });
454
+ expect(propOf(store, 'widget0001', 'count')).toEqual({ kind: 'static', value: 10 });
455
+ });
456
+ it('saves underline, strike and clear as safe rich-text props, and undoes the changes', async () => {
457
+ const doc = fixture();
458
+ const node = doc.nodes['widget0001'];
459
+ if (node === undefined)
460
+ throw new Error('widget missing');
461
+ const initial = {
462
+ type: 'root',
463
+ version: 1,
464
+ children: [
465
+ {
466
+ type: 'paragraph',
467
+ version: 1,
468
+ children: [{ type: 'text', version: 1, text: 'Hello', format: 0 }],
469
+ },
470
+ ],
471
+ };
472
+ const store = await mount('widget0001', {}, { ...doc, nodes: { ...doc.nodes, widget0001: { ...node, props: { rich: s(initial) } } } });
473
+ const dispatch = vi.spyOn(store, 'dispatch');
474
+ const editor = field('rich').querySelector('[role=textbox]').__lexicalEditor;
475
+ await act(async () => {
476
+ editor.update(() => {
477
+ $getRoot().select(0, 1);
478
+ }, { discrete: true });
479
+ });
480
+ const format = async (label) => act(async () => {
481
+ field('rich').querySelector(`[aria-label="${label}"]`)?.click();
482
+ });
483
+ await format('Underline');
484
+ const formatted = propOf(store, 'widget0001', 'rich');
485
+ expect(formatted?.kind).toBe('static');
486
+ expect(dispatch.mock.calls.every(([command]) => command.type === 'node.setProp')).toBe(true);
487
+ expect(JSON.stringify(formatted)).toContain('"format":8');
488
+ await act(async () => {
489
+ store.undo();
490
+ });
491
+ expect(propOf(store, 'widget0001', 'rich')).toEqual(s(initial));
492
+ await act(async () => {
493
+ store.redo();
494
+ });
495
+ expect(JSON.stringify(propOf(store, 'widget0001', 'rich'))).toContain('"format":8');
496
+ await act(async () => {
497
+ editor.update(() => {
498
+ $getRoot().select(0, 1);
499
+ }, { discrete: true });
500
+ });
501
+ await format('Strikethrough');
502
+ expect(JSON.stringify(propOf(store, 'widget0001', 'rich'))).toContain('"format":12');
503
+ Range.prototype.getBoundingClientRect ??= () => new DOMRect();
504
+ Range.prototype.getClientRects ??= () => [];
505
+ await act(async () => editor.update(() => {
506
+ $getRoot().getFirstDescendant()?.selectStart();
507
+ }, { discrete: true }));
508
+ dispatch.mockClear();
509
+ await format('Clear formatting');
510
+ expect(dispatch).not.toHaveBeenCalled();
511
+ expect(JSON.stringify(propOf(store, 'widget0001', 'rich'))).toContain('"format":12');
512
+ await act(async () => editor.update(() => {
513
+ $getRoot().select(0, 1);
514
+ }, { discrete: true }));
515
+ await format('Clear formatting');
516
+ expect(propOf(store, 'widget0001', 'rich')).toEqual(s(initial));
517
+ });
518
+ });
519
+ describe('Advanced template controls', () => {
520
+ it('places tabs before search and writes breakpoint visibility with undo and redo', async () => {
521
+ const store = await mount('widget0001');
522
+ const tabs = container.querySelector('[role=tablist]');
523
+ const search = container.querySelector('.bd-inspector-search input');
524
+ expect(tabs.compareDocumentPosition(search) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
525
+ await openTab('Advanced');
526
+ const chip = container.querySelector('.bd-visibility-chips button:nth-child(2)');
527
+ await act(async () => chip.click());
528
+ expect(store.getState().doc.nodes['widget0001']?.styles?.bp?.['tablet']?.visibility?.hidden).toBe(true);
529
+ await act(async () => store.undo());
530
+ expect(store.getState().doc.nodes['widget0001']?.styles?.bp?.['tablet']?.visibility?.hidden).toBeUndefined();
531
+ await act(async () => store.redo());
532
+ expect(store.getState().doc.nodes['widget0001']?.styles?.bp?.['tablet']?.visibility?.hidden).toBe(true);
533
+ await act(async () => {
534
+ for (const toggle of container.querySelectorAll('.bd-advanced-group > h4 button'))
535
+ toggle.click();
536
+ });
537
+ expect(await axe(container)).toHaveNoViolations();
538
+ });
539
+ });
540
+ describe('Advanced condition commands', () => {
541
+ it('clears a display condition with undo and redo', async () => {
542
+ const base = fixture();
543
+ const node = base.nodes['widget0001'];
544
+ if (!node)
545
+ throw new Error('missing fixture');
546
+ const store = await mount('widget0001', {}, {
547
+ ...base,
548
+ nodes: {
549
+ ...base.nodes,
550
+ widget0001: { ...node, visibleIf: { kind: 'binding', path: 'post.published' } },
551
+ },
552
+ });
553
+ await openTab('Advanced');
554
+ const remove = [...container.querySelectorAll('button')].find((button) => button.textContent === 'Remove the condition');
555
+ await act(async () => remove.click());
556
+ expect(store.getState().doc.nodes['widget0001']?.visibleIf).toBeUndefined();
557
+ await act(async () => store.undo());
558
+ expect(store.getState().doc.nodes['widget0001']?.visibleIf).toEqual({
559
+ kind: 'binding',
560
+ path: 'post.published',
561
+ });
562
+ await act(async () => store.redo());
563
+ expect(store.getState().doc.nodes['widget0001']?.visibleIf).toBeUndefined();
564
+ });
565
+ });
566
+ describe('Heading level segments', () => {
567
+ it('shows six levels before text and writes the numeric prop through history', async () => {
568
+ const store = await mount('widget0001', {}, fixture(), {
569
+ ...widget,
570
+ props: {
571
+ title: widget.props['title'],
572
+ level: p.select({ options: [1, 2, 3, 4, 5, 6], default: 2 }),
573
+ },
574
+ });
575
+ const levels = field('level');
576
+ const segments = levels.querySelectorAll('.bd-segment');
577
+ expect([...segments].map((button) => button.textContent)).toEqual([
578
+ 'H1',
579
+ 'H2',
580
+ 'H3',
581
+ 'H4',
582
+ 'H5',
583
+ 'H6',
584
+ ]);
585
+ expect(levels.compareDocumentPosition(field('title')) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
586
+ await act(async () => segments[2].click());
587
+ expect(propOf(store, 'widget0001', 'level')).toEqual(s(3));
588
+ await act(async () => store.undo());
589
+ expect(propOf(store, 'widget0001', 'level')).toBeUndefined();
590
+ await act(async () => store.redo());
591
+ expect(propOf(store, 'widget0001', 'level')).toEqual(s(3));
592
+ });
593
+ });
@@ -1,7 +1,22 @@
1
1
  import type { ComponentMeta, PageNode, PropDef, Value } from '@next-buildr/core';
2
2
  import { propLabel } from './controls/index.ts';
3
+ import { type PropReading } from './value.ts';
3
4
  export declare const isAdvancedProp: (def: PropDef) => boolean;
4
5
  export { propLabel };
6
+ /**
7
+ * The group a prop is shown in. The background props of a container carry no `group`; they are
8
+ * collected under "Background" by their names (`background*` and `overlay*`), so the editor needs
9
+ * no knowledge of the component.
10
+ */
11
+ export declare function propGroup(name: string, def: PropDef): string;
12
+ /** A text prop that always holds an address outside the site (the iframe's `url`, ADR-028). */
13
+ export declare const isExternalUrlProp: (type: string, name: string, def: PropDef) => boolean;
14
+ /**
15
+ * Text has three ways to write its content (ADR-026): `mode` picks one of `text`, `rich` and
16
+ * `html`. The inspector shows the mode as a switch and only the field of the chosen mode. Found by
17
+ * the shape of the props, so the editor needs no knowledge of the component.
18
+ */
19
+ export declare function hasTextModes(props: Readonly<Record<string, PropDef>>): boolean;
5
20
  export interface PropsPanelProps {
6
21
  readonly node: PageNode;
7
22
  readonly meta: ComponentMeta;
@@ -10,6 +25,10 @@ export interface PropsPanelProps {
10
25
  readonly locale: string | undefined;
11
26
  readonly defaultLocale: string | undefined;
12
27
  readonly disabled: boolean;
28
+ /** Lower-case text the labels must contain (the inspector search); empty shows everything. */
29
+ readonly query?: string;
30
+ /** Other fields on the same tab already match the query: no "no match" message. */
31
+ readonly othersMatch?: boolean;
13
32
  readonly onChange: (prop: string, def: PropDef, value: unknown) => void;
14
33
  readonly onReset: (prop: string, def: PropDef) => void;
15
34
  /** Writes a binding or a formula (PB-081). */
@@ -17,6 +36,23 @@ export interface PropsPanelProps {
17
36
  /** Back from a binding or a formula to a fixed value. */
18
37
  readonly onFixed?: (prop: string, def: PropDef) => void;
19
38
  }
39
+ export declare function Field(props: {
40
+ readonly name: string;
41
+ readonly def: PropDef;
42
+ readonly reading: PropReading;
43
+ readonly raw: Value | undefined;
44
+ readonly disabled: boolean;
45
+ readonly translating: boolean;
46
+ readonly onChange: PropsPanelProps['onChange'];
47
+ readonly onReset: PropsPanelProps['onReset'];
48
+ readonly onSetValue: PropsPanelProps['onSetValue'];
49
+ readonly onFixed: PropsPanelProps['onFixed'];
50
+ readonly nameFor: (text: string) => string;
51
+ /** The `mode` prop of a text with three modes: drawn as a switch. */
52
+ readonly textMode?: boolean;
53
+ /** The prop is an external address: it is added through the ADR-028 warning. */
54
+ readonly externalUrl?: boolean;
55
+ }): import("react").JSX.Element;
20
56
  /**
21
57
  * The props of a component as controls, grouped by their `group` (docs/editor.md#inspector). A
22
58
  * control writes with `node.setProp` (typing coalesces into one undo step through the command's
@@ -1 +1 @@
1
- {"version":3,"file":"props-panel.d.ts","sourceRoot":"","sources":["../../../src/panels/inspector/props-panel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAIjF,OAAO,EAAE,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAQ/D,eAAO,MAAM,cAAc,QAAS,OAAO,YACgB,CAAC;AAI5D,OAAO,EAAE,SAAS,EAAE,CAAC;AA2CrB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACxE,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACvD,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACzE,yDAAyD;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CACzD;AA8GD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,sCAkEhD"}
1
+ {"version":3,"file":"props-panel.d.ts","sourceRoot":"","sources":["../../../src/panels/inspector/props-panel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAMjF,OAAO,EAAsB,SAAS,EAAiB,MAAM,qBAAqB,CAAC;AAInF,OAAO,EAAE,KAAK,WAAW,EAA+B,MAAM,YAAY,CAAC;AAO3E,eAAO,MAAM,cAAc,QAAS,OAAO,YACgB,CAAC;AAI5D,OAAO,EAAE,SAAS,EAAE,CAAC;AAIrB;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,CAG5D;AASD,+FAA+F;AAC/F,eAAO,MAAM,iBAAiB,SAAU,MAAM,QAAQ,MAAM,OAAO,OAAO,KAAG,OACV,CAAC;AAEpE;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAS9E;AA2CD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,UAAU,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,mFAAmF;IACnF,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACxE,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IACvD,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACzE,yDAAyD;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CACzD;AAsBD,wBAAgB,KAAK,CAAC,KAAK,EAAE;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,KAAK,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;IAC7C,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;IACnD,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;CAChC,+BAyJA;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,sCAuGhD"}
@@ -1,8 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useId, useState } from 'react';
3
+ import { componentMeta, useSourceManifest } from '../../app/manifest.js';
3
4
  import { useT } from '../../messages/index.js';
4
- import { Icon, IconButton } from '../../ui/index.js';
5
- import { propLabel, renderControl } from './controls/index.js';
5
+ import { useEditor } from '../../store/index.js';
6
+ import { Icon, IconButton, SegmentedControl } from '../../ui/index.js';
7
+ import { ExternalUrlControl, propLabel, renderControl } from './controls/index.js';
8
+ import { parseNumber } from './controls/number.js';
9
+ import { formatDefault } from './default-hint.js';
10
+ import { ScrubLabel } from './scrub-label.js';
6
11
  import { readProp, translationLocale } from './value.js';
7
12
  import { TranslationHint } from './values/translation.js';
8
13
  import { ValueEditor } from './values/value-editor.js';
@@ -11,6 +16,38 @@ const ADVANCED_GROUPS = new Set(['advanced', 'accessibility']);
11
16
  export const isAdvancedProp = (def) => def.group !== undefined && ADVANCED_GROUPS.has(def.group);
12
17
  const titleCase = (text) => text.charAt(0).toUpperCase() + text.slice(1);
13
18
  export { propLabel };
19
+ const TEXT_MODES = ['plain', 'rich', 'html'];
20
+ /**
21
+ * The group a prop is shown in. The background props of a container carry no `group`; they are
22
+ * collected under "Background" by their names (`background*` and `overlay*`), so the editor needs
23
+ * no knowledge of the component.
24
+ */
25
+ export function propGroup(name, def) {
26
+ if (def.group !== undefined)
27
+ return def.group;
28
+ return /^(background|overlay)[A-Z]/.test(name) ? 'background' : '';
29
+ }
30
+ /** Short selects that read better as a row of segments (media fit, scrolling and overlay tone). */
31
+ const SEGMENTED_SELECTS = new Set([
32
+ 'backgroundFit',
33
+ 'backgroundAttachment',
34
+ 'overlayTone',
35
+ ]);
36
+ /** A text prop that always holds an address outside the site (the iframe's `url`, ADR-028). */
37
+ export const isExternalUrlProp = (type, name, def) => type === 'buildr/iframe' && name === 'url' && def.kind === 'text';
38
+ /**
39
+ * Text has three ways to write its content (ADR-026): `mode` picks one of `text`, `rich` and
40
+ * `html`. The inspector shows the mode as a switch and only the field of the chosen mode. Found by
41
+ * the shape of the props, so the editor needs no knowledge of the component.
42
+ */
43
+ export function hasTextModes(props) {
44
+ const mode = props['mode'];
45
+ return (mode?.kind === 'select' &&
46
+ TEXT_MODES.every((value) => mode.options.includes(value)) &&
47
+ props['text'] !== undefined &&
48
+ props['rich']?.kind === 'richText' &&
49
+ props['html']?.kind === 'textarea');
50
+ }
14
51
  /** Short controls sit on one row with their label; long ones are stacked under it. */
15
52
  const ROW_KINDS = new Set(['boolean', 'select', 'number', 'icon']);
16
53
  const storageKey = (type) => `buildr.editor.inspector.groups.${type}`;
@@ -51,12 +88,13 @@ function useClosedGroups(type) {
51
88
  return { closed, toggle };
52
89
  }
53
90
  /** A hint shown under a control: what the default is, and the limits a value must keep. */
54
- function hintFor(def, t) {
91
+ function hintFor(def, t,
92
+ /** The component's label when the default text is the component's own English name. */
93
+ nameFor) {
55
94
  const parts = [];
56
- const shown = String(def.default);
57
- if (def.kind !== 'list' && def.kind !== 'object' && def.kind !== 'richText' && shown !== '') {
95
+ const shown = formatDefault(def, t, nameFor);
96
+ if (shown !== undefined)
58
97
  parts.push(`${t('inspector.default')}: ${shown}`);
59
- }
60
98
  if ((def.kind === 'text' || def.kind === 'textarea') && def.maxLength !== undefined) {
61
99
  parts.push(`${t('inspector.maxLength')}: ${def.maxLength}`);
62
100
  }
@@ -68,15 +106,34 @@ function hintFor(def, t) {
68
106
  }
69
107
  return parts.join(' · ');
70
108
  }
71
- function Field(props) {
109
+ export function Field(props) {
72
110
  const { name, def, reading, disabled, translating } = props;
73
111
  const t = useT();
74
112
  const id = useId();
113
+ const authorCode = useEditor().authorCode;
75
114
  const hintId = `${id}-hint`;
76
- const label = propLabel(name, def);
77
- const hint = hintFor(def, t);
115
+ const label = props.textMode === true
116
+ ? t('inspector.text.mode')
117
+ : name === 'level'
118
+ ? t('inspector.content.level')
119
+ : propLabel(name, def);
120
+ const hint = props.textMode === true ? '' : hintFor(def, t, props.nameFor);
78
121
  const editable = reading.mode === 'static';
79
- const control = renderControl(def, {
122
+ const current = String(reading.value);
123
+ const control = props.textMode === true ? (_jsx(SegmentedControl, { label: t('inspector.text.mode'), value: current, disabled: disabled, options: TEXT_MODES.map((value) => ({
124
+ value,
125
+ label: t(`inspector.text.mode.${value}`),
126
+ disabled: value === 'html' && !authorCode && current !== 'html',
127
+ })), onValueChange: (value) => props.onChange(name, def, value) })) : name === 'level' &&
128
+ def.kind === 'select' &&
129
+ def.options.every((value) => typeof value === 'number' && value >= 1 && value <= 6) ? (_jsx(SegmentedControl, { label: t('inspector.content.level'), value: String(reading.value), disabled: disabled, options: def.options.map((value) => ({ value: String(value), label: `H${value}` })), onValueChange: (value) => props.onChange(name, def, Number(value)) })) : props.externalUrl === true ? (_jsx(ExternalUrlControl, { id: id, label: label, describedBy: hint === '' ? undefined : hintId, value: reading.value, disabled: disabled, onChange: (value) => props.onChange(name, def, value) })) : SEGMENTED_SELECTS.has(name) && def.kind === 'select' && def.options.length <= 3 ? (_jsx(SegmentedControl, { label: label, value: String(reading.value), disabled: disabled, options: def.options.map((option) => ({
130
+ value: String(option),
131
+ label: def.optionLabels?.[String(option)] ?? String(option),
132
+ })), onValueChange: (chosen) => {
133
+ const option = def.options.find((candidate) => String(candidate) === chosen);
134
+ if (option !== undefined)
135
+ props.onChange(name, def, option);
136
+ } })) : (renderControl(def, {
80
137
  id,
81
138
  def,
82
139
  label,
@@ -84,9 +141,13 @@ function Field(props) {
84
141
  value: reading.value,
85
142
  disabled,
86
143
  onChange: (value) => props.onChange(name, def, value),
87
- });
88
- const layout = ROW_KINDS.has(def.kind) ? 'row' : 'stack';
89
- return (_jsxs("div", { className: "bd-field", "data-prop": name, "data-kind": def.kind, "data-layout": layout, "data-untranslated": translating && !reading.isSet ? true : undefined, children: [_jsxs("div", { className: "bd-field-head", children: [control !== null && editable ? (_jsxs("label", { htmlFor: id, className: "bd-field-label", children: [label, translating ? (_jsxs("span", { className: "bd-field-locale", children: [" (", t('inspector.translation'), ")"] })) : null] })) : (_jsx("span", { className: "bd-field-label", children: label })), reading.isSet ? (_jsx(IconButton, { variant: "ghost", icon: "rotate-ccw", className: "bd-field-reset", disabled: disabled, label: `${t(translating ? 'translation.remove' : 'inspector.reset')}: ${label}`, onClick: () => props.onReset(name, def) })) : null] }), _jsx("div", { className: "bd-field-body", children: _jsx(ValueEditor, { def: def, label: label, raw: props.raw, disabled: disabled, staticControl: control, onSet: (value) => props.onSetValue?.(name, def, value), onFixed: () => props.onFixed?.(name, def) }) }), translating && editable ? (_jsx(TranslationHint, { translated: reading.isSet, disabled: disabled, label: label, onTranslate: () => props.onChange(name, def, reading.value) })) : null, editable && control === null ? (_jsx("p", { className: "bd-field-unsupported", children: t('inspector.unsupported') })) : null, hint !== '' ? (_jsx("p", { className: "bd-field-hint", id: hintId, children: hint })) : null] }));
144
+ }));
145
+ const layout = ROW_KINDS.has(def.kind) && !SEGMENTED_SELECTS.has(name) ? 'row' : 'stack';
146
+ return (_jsxs("div", { className: "bd-field", "data-prop": name, "data-kind": def.kind, "data-layout": layout, "data-untranslated": translating && !reading.isSet ? true : undefined, children: [_jsxs("div", { className: "bd-field-head", children: [control !== null && editable ? (def.kind === 'number' ? (_jsxs(ScrubLabel, { htmlFor: id, value: String(reading.value ?? def.default), step: def.step ?? 1, min: def.min, max: def.max, disabled: disabled, onValueChange: (text) => {
147
+ const next = parseNumber(text, def);
148
+ if (next !== undefined)
149
+ props.onChange(name, def, next);
150
+ }, children: [label, translating ? (_jsxs("span", { className: "bd-field-locale", children: [" (", t('inspector.translation'), ")"] })) : null] })) : (_jsxs("label", { htmlFor: id, className: "bd-field-label", children: [label, translating ? (_jsxs("span", { className: "bd-field-locale", children: [" (", t('inspector.translation'), ")"] })) : null] }))) : (_jsx("span", { className: "bd-field-label", children: label })), reading.isSet ? (_jsx(IconButton, { variant: "ghost", icon: "rotate-ccw", className: "bd-field-reset", disabled: disabled, label: `${t(translating ? 'translation.remove' : 'inspector.reset')}: ${label}`, onClick: () => props.onReset(name, def) })) : null] }), _jsx("div", { className: "bd-field-body", children: _jsx(ValueEditor, { def: def, label: label, raw: props.raw, disabled: disabled, staticControl: control, onSet: (value) => props.onSetValue?.(name, def, value), onFixed: () => props.onFixed?.(name, def) }) }), translating && editable ? (_jsx(TranslationHint, { translated: reading.isSet, disabled: disabled, label: label, onTranslate: () => props.onChange(name, def, reading.value) })) : null, editable && control === null ? (_jsx("p", { className: "bd-field-unsupported", children: t('inspector.unsupported') })) : null, hint !== '' ? (_jsx("p", { className: "bd-field-hint", id: hintId, children: hint })) : null] }));
90
151
  }
91
152
  /**
92
153
  * The props of a component as controls, grouped by their `group` (docs/editor.md#inspector). A
@@ -96,22 +157,43 @@ function Field(props) {
96
157
  export function PropsPanel(props) {
97
158
  const t = useT();
98
159
  const { node, meta, scope, locale, defaultLocale } = props;
160
+ const source = componentMeta(useSourceManifest(), node.type);
99
161
  const { closed, toggle } = useClosedGroups(node.type);
100
162
  const panelId = useId();
101
- const entries = Object.entries(meta.props).filter(([, def]) => isAdvancedProp(def) === (scope === 'advanced'));
163
+ const query = props.query ?? '';
164
+ const all = Object.entries(meta.props).filter(([, def]) => isAdvancedProp(def) === (scope === 'advanced'));
165
+ all.sort(([a], [b]) => Number(b === 'level') - Number(a === 'level'));
166
+ const modal = hasTextModes(meta.props);
167
+ const modeDef = meta.props['mode'];
168
+ const modeValue = modal && modeDef !== undefined
169
+ ? readProp(node, 'mode', modeDef, locale, defaultLocale).value
170
+ : undefined;
171
+ const activeMode = typeof modeValue === 'string' ? modeValue : 'plain';
172
+ // Only the field of the chosen text mode is shown (plain: text, rich: rich, html: html).
173
+ const inMode = (name) => !modal ||
174
+ !['text', 'rich', 'html'].includes(name) ||
175
+ (name === 'text' ? 'plain' : name) === activeMode;
176
+ const entries = all.filter(([name, def]) => inMode(name) && (query === '' || propLabel(name, def).toLowerCase().includes(query)));
177
+ if (entries.length === 0 && all.length > 0) {
178
+ if (props.othersMatch === true)
179
+ return null;
180
+ return (_jsx("p", { className: "bd-inspector-empty", "data-state": "no-match", children: t('inspector.search.noMatch').replace('{query}', query) }));
181
+ }
102
182
  if (entries.length === 0) {
103
183
  return scope === 'content' ? (_jsxs("div", { className: "bd-inspector-empty", "data-state": "no-props", children: [_jsx(Icon, { name: "box", size: "md" }), _jsx("p", { className: "bd-inspector-empty-title", children: t('inspector.noProps') })] })) : null;
104
184
  }
185
+ // A default text that is the component's English name ("Heading") reads as its label in the UI language.
186
+ const nameFor = (text) => source?.label !== undefined && text === source.label ? (meta.label ?? text) : text;
105
187
  const groups = new Map();
106
188
  for (const entry of entries) {
107
- const group = entry[1].group ?? '';
189
+ const group = propGroup(entry[0], entry[1]);
108
190
  const list = groups.get(group);
109
191
  if (list === undefined)
110
192
  groups.set(group, [entry]);
111
193
  else
112
194
  list.push(entry);
113
195
  }
114
- return (_jsx("div", { className: "bd-props", children: [...groups].map(([group, list]) => (_jsxs("section", { className: "bd-props-group", "data-group": group, children: [group !== '' ? (_jsx("h4", { className: "bd-props-heading", children: _jsxs("button", { type: "button", className: "bd-props-toggle", "aria-expanded": !closed.has(group), "aria-controls": `${panelId}-${group}`, onClick: () => toggle(group), children: [_jsx(Icon, { name: closed.has(group) ? 'chevron-right' : 'chevron-down' }), titleCase(group)] }) })) : null, _jsx("div", { id: `${panelId}-${group}`, className: "bd-props-fields", hidden: closed.has(group), children: list.map(([name, def]) => (_jsx(Field, { name: name, def: def, reading: readProp(node, name, def, locale, defaultLocale), raw: node.props !== undefined && Object.hasOwn(node.props, name)
196
+ return (_jsx("div", { className: "bd-props", children: [...groups].map(([group, list]) => (_jsxs("section", { className: "bd-props-group", "data-group": group, children: [group !== '' ? (_jsx("h4", { className: "bd-props-heading", children: _jsxs("button", { type: "button", className: "bd-props-toggle", "aria-expanded": !closed.has(group), "aria-controls": `${panelId}-${group}`, onClick: () => toggle(group), children: [_jsx(Icon, { name: closed.has(group) ? 'chevron-right' : 'chevron-down' }), group === 'background' ? t('inspector.group.background') : titleCase(group)] }) })) : null, _jsx("div", { id: `${panelId}-${group}`, className: "bd-props-fields", hidden: closed.has(group) && query === '', children: list.map(([name, def]) => (_jsx(Field, { name: name, def: def, reading: readProp(node, name, def, locale, defaultLocale), raw: node.props !== undefined && Object.hasOwn(node.props, name)
115
197
  ? node.props[name]
116
- : undefined, disabled: props.disabled, translating: translationLocale(def, locale, defaultLocale) !== undefined, onChange: props.onChange, onReset: props.onReset, onSetValue: props.onSetValue, onFixed: props.onFixed }, name))) })] }, group))) }));
198
+ : undefined, disabled: props.disabled, translating: translationLocale(def, locale, defaultLocale) !== undefined, onChange: props.onChange, onReset: props.onReset, onSetValue: props.onSetValue, onFixed: props.onFixed, nameFor: nameFor, textMode: modal && name === 'mode', externalUrl: isExternalUrlProp(node.type, name, def) }, name))) })] }, group))) }));
117
199
  }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=props-panel.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"props-panel.test.d.ts","sourceRoot":"","sources":["../../../src/panels/inspector/props-panel.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import { p } from '@next-buildr/core';
2
+ import { expect, it } from 'vitest';
3
+ import { isExternalUrlProp, propGroup } from './props-panel.js';
4
+ it('collects background and overlay props in the background group', () => {
5
+ const image = p.media({ label: 'Background image', accept: ['image'] });
6
+ expect(propGroup('backgroundImage', image)).toBe('background');
7
+ expect(propGroup('overlayTone', p.text({ label: 'x' }))).toBe('background');
8
+ expect(propGroup('bleed', p.boolean({ label: 'x', default: false }))).toBe('');
9
+ expect(propGroup('background', p.text({ label: 'x' }))).toBe('');
10
+ expect(propGroup('width', p.text({ label: 'x', group: 'advanced' }))).toBe('advanced');
11
+ });
12
+ it('treats only the iframe url as an always-external text prop', () => {
13
+ const text = p.text({ label: 'Address', default: '' });
14
+ expect(isExternalUrlProp('buildr/iframe', 'url', text)).toBe(true);
15
+ expect(isExternalUrlProp('buildr/iframe', 'title', text)).toBe(false);
16
+ expect(isExternalUrlProp('buildr/link', 'url', text)).toBe(false);
17
+ });
@@ -0,0 +1,14 @@
1
+ import { type ReactNode } from 'react';
2
+ /** Pointer scrubbing supplements keyboard controls and records the entire gesture as one undo step. */
3
+ export declare function ScrubLabel(props: {
4
+ readonly htmlFor: string;
5
+ readonly children: ReactNode;
6
+ readonly value: string;
7
+ readonly step?: number;
8
+ readonly min?: number | undefined;
9
+ readonly max?: number | undefined;
10
+ readonly unit?: string;
11
+ readonly disabled: boolean;
12
+ readonly onValueChange: (value: string) => void;
13
+ }): import("react").JSX.Element;
14
+ //# sourceMappingURL=scrub-label.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrub-label.d.ts","sourceRoot":"","sources":["../../../src/panels/inspector/scrub-label.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAkC,MAAM,OAAO,CAAC;AAoBvE,uGAAuG;AACvG,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD,+BAyEA"}