@next-buildr/editor 0.0.0-stage → 2.0.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 (471) hide show
  1. package/LICENSE +21 -0
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/app/builder-editor.d.ts +8 -0
  4. package/dist/app/builder-editor.d.ts.map +1 -0
  5. package/dist/app/builder-editor.js +14 -0
  6. package/dist/app/builder-editor.test.d.ts +2 -0
  7. package/dist/app/builder-editor.test.d.ts.map +1 -0
  8. package/dist/app/builder-editor.test.js +199 -0
  9. package/dist/app/config.d.ts +59 -0
  10. package/dist/app/config.d.ts.map +1 -0
  11. package/dist/app/config.js +18 -0
  12. package/dist/app/content-language.test.d.ts +2 -0
  13. package/dist/app/content-language.test.d.ts.map +1 -0
  14. package/dist/app/content-language.test.js +157 -0
  15. package/dist/app/editor-app.d.ts +17 -0
  16. package/dist/app/editor-app.d.ts.map +1 -0
  17. package/dist/app/editor-app.js +206 -0
  18. package/dist/app/editor-app.test.d.ts +2 -0
  19. package/dist/app/editor-app.test.d.ts.map +1 -0
  20. package/dist/app/editor-app.test.js +135 -0
  21. package/dist/app/layout.d.ts +32 -0
  22. package/dist/app/layout.d.ts.map +1 -0
  23. package/dist/app/layout.js +82 -0
  24. package/dist/app/manifest.d.ts +12 -0
  25. package/dist/app/manifest.d.ts.map +1 -0
  26. package/dist/app/manifest.js +17 -0
  27. package/dist/app/shell-panels.d.ts +15 -0
  28. package/dist/app/shell-panels.d.ts.map +1 -0
  29. package/dist/app/shell-panels.js +5 -0
  30. package/dist/app/small-screen.d.ts +12 -0
  31. package/dist/app/small-screen.d.ts.map +1 -0
  32. package/dist/app/small-screen.js +33 -0
  33. package/dist/app/small-screen.test.d.ts +2 -0
  34. package/dist/app/small-screen.test.d.ts.map +1 -0
  35. package/dist/app/small-screen.test.js +108 -0
  36. package/dist/app/status-info.d.ts +14 -0
  37. package/dist/app/status-info.d.ts.map +1 -0
  38. package/dist/app/status-info.js +34 -0
  39. package/dist/app/use-resizable.d.ts +34 -0
  40. package/dist/app/use-resizable.d.ts.map +1 -0
  41. package/dist/app/use-resizable.js +84 -0
  42. package/dist/canvas-host/canvas-frame.d.ts +53 -0
  43. package/dist/canvas-host/canvas-frame.d.ts.map +1 -0
  44. package/dist/canvas-host/canvas-frame.js +146 -0
  45. package/dist/canvas-host/canvas-frame.test.d.ts +2 -0
  46. package/dist/canvas-host/canvas-frame.test.d.ts.map +1 -0
  47. package/dist/canvas-host/canvas-frame.test.js +91 -0
  48. package/dist/canvas-host/host.d.ts +109 -0
  49. package/dist/canvas-host/host.d.ts.map +1 -0
  50. package/dist/canvas-host/host.js +293 -0
  51. package/dist/canvas-host/host.test.d.ts +2 -0
  52. package/dist/canvas-host/host.test.d.ts.map +1 -0
  53. package/dist/canvas-host/host.test.js +398 -0
  54. package/dist/canvas-host/index.d.ts +5 -0
  55. package/dist/canvas-host/index.d.ts.map +1 -0
  56. package/dist/canvas-host/index.js +2 -0
  57. package/dist/clipboard/clipboard.d.ts +38 -0
  58. package/dist/clipboard/clipboard.d.ts.map +1 -0
  59. package/dist/clipboard/clipboard.js +160 -0
  60. package/dist/clipboard/clipboard.test.d.ts +2 -0
  61. package/dist/clipboard/clipboard.test.d.ts.map +1 -0
  62. package/dist/clipboard/clipboard.test.js +457 -0
  63. package/dist/clipboard/format.d.ts +27 -0
  64. package/dist/clipboard/format.d.ts.map +1 -0
  65. package/dist/clipboard/format.js +37 -0
  66. package/dist/clipboard/index.d.ts +6 -0
  67. package/dist/clipboard/index.d.ts.map +1 -0
  68. package/dist/clipboard/index.js +3 -0
  69. package/dist/clipboard/react.d.ts +20 -0
  70. package/dist/clipboard/react.d.ts.map +1 -0
  71. package/dist/clipboard/react.js +71 -0
  72. package/dist/dialogs/index.d.ts +2 -0
  73. package/dist/dialogs/index.d.ts.map +1 -0
  74. package/dist/dialogs/index.js +1 -0
  75. package/dist/dialogs/media-picker/index.d.ts +7 -0
  76. package/dist/dialogs/media-picker/index.d.ts.map +1 -0
  77. package/dist/dialogs/media-picker/index.js +3 -0
  78. package/dist/dialogs/media-picker/library.d.ts +17 -0
  79. package/dist/dialogs/media-picker/library.d.ts.map +1 -0
  80. package/dist/dialogs/media-picker/library.js +9 -0
  81. package/dist/dialogs/media-picker/media-picker.d.ts +18 -0
  82. package/dist/dialogs/media-picker/media-picker.d.ts.map +1 -0
  83. package/dist/dialogs/media-picker/media-picker.js +99 -0
  84. package/dist/dialogs/media-picker/media-picker.test.d.ts +2 -0
  85. package/dist/dialogs/media-picker/media-picker.test.d.ts.map +1 -0
  86. package/dist/dialogs/media-picker/media-picker.test.js +161 -0
  87. package/dist/dialogs/media-picker/media-ref.d.ts +28 -0
  88. package/dist/dialogs/media-picker/media-ref.d.ts.map +1 -0
  89. package/dist/dialogs/media-picker/media-ref.js +52 -0
  90. package/dist/dnd/check.d.ts +8 -0
  91. package/dist/dnd/check.d.ts.map +1 -0
  92. package/dist/dnd/check.js +12 -0
  93. package/dist/dnd/destinations.d.ts +15 -0
  94. package/dist/dnd/destinations.d.ts.map +1 -0
  95. package/dist/dnd/destinations.js +43 -0
  96. package/dist/dnd/dnd-react.test.d.ts +2 -0
  97. package/dist/dnd/dnd-react.test.d.ts.map +1 -0
  98. package/dist/dnd/dnd-react.test.js +93 -0
  99. package/dist/dnd/dnd.test.d.ts +2 -0
  100. package/dist/dnd/dnd.test.d.ts.map +1 -0
  101. package/dist/dnd/dnd.test.js +327 -0
  102. package/dist/dnd/engine.d.ts +85 -0
  103. package/dist/dnd/engine.d.ts.map +1 -0
  104. package/dist/dnd/engine.js +185 -0
  105. package/dist/dnd/fragment.d.ts +6 -0
  106. package/dist/dnd/fragment.d.ts.map +1 -0
  107. package/dist/dnd/fragment.js +18 -0
  108. package/dist/dnd/geometry.d.ts +30 -0
  109. package/dist/dnd/geometry.d.ts.map +1 -0
  110. package/dist/dnd/geometry.js +31 -0
  111. package/dist/dnd/index.d.ts +14 -0
  112. package/dist/dnd/index.d.ts.map +1 -0
  113. package/dist/dnd/index.js +7 -0
  114. package/dist/dnd/move-to-dialog.d.ts +13 -0
  115. package/dist/dnd/move-to-dialog.d.ts.map +1 -0
  116. package/dist/dnd/move-to-dialog.js +30 -0
  117. package/dist/dnd/react.d.ts +43 -0
  118. package/dist/dnd/react.d.ts.map +1 -0
  119. package/dist/dnd/react.js +185 -0
  120. package/dist/dnd/tree-target.d.ts +29 -0
  121. package/dist/dnd/tree-target.d.ts.map +1 -0
  122. package/dist/dnd/tree-target.js +97 -0
  123. package/dist/fonts/LICENSE-inter.txt +93 -0
  124. package/dist/fonts/inter-latin-400-normal.woff2 +0 -0
  125. package/dist/fonts/inter-latin-500-normal.woff2 +0 -0
  126. package/dist/fonts/inter-latin-600-normal.woff2 +0 -0
  127. package/dist/fonts/inter-latin-ext-400-normal.woff2 +0 -0
  128. package/dist/fonts/inter-latin-ext-500-normal.woff2 +0 -0
  129. package/dist/fonts/inter-latin-ext-600-normal.woff2 +0 -0
  130. package/dist/index.d.ts +22 -0
  131. package/dist/index.d.ts.map +1 -0
  132. package/dist/index.js +21 -0
  133. package/dist/messages/en.d.ts +335 -0
  134. package/dist/messages/en.d.ts.map +1 -0
  135. package/dist/messages/en.js +332 -0
  136. package/dist/messages/index.d.ts +16 -0
  137. package/dist/messages/index.d.ts.map +1 -0
  138. package/dist/messages/index.js +22 -0
  139. package/dist/messages/pl.d.ts +3 -0
  140. package/dist/messages/pl.d.ts.map +1 -0
  141. package/dist/messages/pl.js +327 -0
  142. package/dist/panels/breadcrumbs/breadcrumbs.d.ts +6 -0
  143. package/dist/panels/breadcrumbs/breadcrumbs.d.ts.map +1 -0
  144. package/dist/panels/breadcrumbs/breadcrumbs.js +24 -0
  145. package/dist/panels/breadcrumbs/breadcrumbs.test.d.ts +2 -0
  146. package/dist/panels/breadcrumbs/breadcrumbs.test.d.ts.map +1 -0
  147. package/dist/panels/breadcrumbs/breadcrumbs.test.js +56 -0
  148. package/dist/panels/index.d.ts +9 -0
  149. package/dist/panels/index.d.ts.map +1 -0
  150. package/dist/panels/index.js +6 -0
  151. package/dist/panels/insert/catalog.d.ts +30 -0
  152. package/dist/panels/insert/catalog.d.ts.map +1 -0
  153. package/dist/panels/insert/catalog.js +76 -0
  154. package/dist/panels/insert/catalog.order.test.d.ts +2 -0
  155. package/dist/panels/insert/catalog.order.test.d.ts.map +1 -0
  156. package/dist/panels/insert/catalog.order.test.js +17 -0
  157. package/dist/panels/insert/category-name.d.ts +4 -0
  158. package/dist/panels/insert/category-name.d.ts.map +1 -0
  159. package/dist/panels/insert/category-name.js +8 -0
  160. package/dist/panels/insert/index.d.ts +3 -0
  161. package/dist/panels/insert/index.d.ts.map +1 -0
  162. package/dist/panels/insert/index.js +2 -0
  163. package/dist/panels/insert/insert-panel.d.ts +7 -0
  164. package/dist/panels/insert/insert-panel.d.ts.map +1 -0
  165. package/dist/panels/insert/insert-panel.js +155 -0
  166. package/dist/panels/insert/insert-panel.test.d.ts +2 -0
  167. package/dist/panels/insert/insert-panel.test.d.ts.map +1 -0
  168. package/dist/panels/insert/insert-panel.test.js +323 -0
  169. package/dist/panels/insert/target.d.ts +17 -0
  170. package/dist/panels/insert/target.d.ts.map +1 -0
  171. package/dist/panels/insert/target.js +48 -0
  172. package/dist/panels/inspector/controls/boolean.d.ts +4 -0
  173. package/dist/panels/inspector/controls/boolean.d.ts.map +1 -0
  174. package/dist/panels/inspector/controls/boolean.js +4 -0
  175. package/dist/panels/inspector/controls/compound.d.ts +15 -0
  176. package/dist/panels/inspector/controls/compound.d.ts.map +1 -0
  177. package/dist/panels/inspector/controls/compound.js +99 -0
  178. package/dist/panels/inspector/controls/compound.test.d.ts +2 -0
  179. package/dist/panels/inspector/controls/compound.test.d.ts.map +1 -0
  180. package/dist/panels/inspector/controls/compound.test.js +195 -0
  181. package/dist/panels/inspector/controls/icon.d.ts +5 -0
  182. package/dist/panels/inspector/controls/icon.d.ts.map +1 -0
  183. package/dist/panels/inspector/controls/icon.js +6 -0
  184. package/dist/panels/inspector/controls/index.d.ts +13 -0
  185. package/dist/panels/inspector/controls/index.d.ts.map +1 -0
  186. package/dist/panels/inspector/controls/index.js +11 -0
  187. package/dist/panels/inspector/controls/label.d.ts +4 -0
  188. package/dist/panels/inspector/controls/label.d.ts.map +1 -0
  189. package/dist/panels/inspector/controls/label.js +8 -0
  190. package/dist/panels/inspector/controls/link.d.ts +5 -0
  191. package/dist/panels/inspector/controls/link.d.ts.map +1 -0
  192. package/dist/panels/inspector/controls/link.js +6 -0
  193. package/dist/panels/inspector/controls/media.d.ts +9 -0
  194. package/dist/panels/inspector/controls/media.d.ts.map +1 -0
  195. package/dist/panels/inspector/controls/media.js +21 -0
  196. package/dist/panels/inspector/controls/number.d.ts +10 -0
  197. package/dist/panels/inspector/controls/number.d.ts.map +1 -0
  198. package/dist/panels/inspector/controls/number.js +33 -0
  199. package/dist/panels/inspector/controls/rich-text-model.d.ts +20 -0
  200. package/dist/panels/inspector/controls/rich-text-model.d.ts.map +1 -0
  201. package/dist/panels/inspector/controls/rich-text-model.js +91 -0
  202. package/dist/panels/inspector/controls/rich-text.d.ts +10 -0
  203. package/dist/panels/inspector/controls/rich-text.d.ts.map +1 -0
  204. package/dist/panels/inspector/controls/rich-text.js +159 -0
  205. package/dist/panels/inspector/controls/select.d.ts +5 -0
  206. package/dist/panels/inspector/controls/select.d.ts.map +1 -0
  207. package/dist/panels/inspector/controls/select.js +16 -0
  208. package/dist/panels/inspector/controls/select.test.d.ts +2 -0
  209. package/dist/panels/inspector/controls/select.test.d.ts.map +1 -0
  210. package/dist/panels/inspector/controls/select.test.js +43 -0
  211. package/dist/panels/inspector/controls/text.d.ts +4 -0
  212. package/dist/panels/inspector/controls/text.d.ts.map +1 -0
  213. package/dist/panels/inspector/controls/text.js +5 -0
  214. package/dist/panels/inspector/controls/textarea.d.ts +4 -0
  215. package/dist/panels/inspector/controls/textarea.d.ts.map +1 -0
  216. package/dist/panels/inspector/controls/textarea.js +4 -0
  217. package/dist/panels/inspector/controls/types.d.ts +16 -0
  218. package/dist/panels/inspector/controls/types.d.ts.map +1 -0
  219. package/dist/panels/inspector/controls/types.js +1 -0
  220. package/dist/panels/inspector/index.d.ts +17 -0
  221. package/dist/panels/inspector/index.d.ts.map +1 -0
  222. package/dist/panels/inspector/index.js +9 -0
  223. package/dist/panels/inspector/inspector.d.ts +16 -0
  224. package/dist/panels/inspector/inspector.d.ts.map +1 -0
  225. package/dist/panels/inspector/inspector.js +116 -0
  226. package/dist/panels/inspector/inspector.test.d.ts +2 -0
  227. package/dist/panels/inspector/inspector.test.d.ts.map +1 -0
  228. package/dist/panels/inspector/inspector.test.js +328 -0
  229. package/dist/panels/inspector/props-panel.d.ts +26 -0
  230. package/dist/panels/inspector/props-panel.d.ts.map +1 -0
  231. package/dist/panels/inspector/props-panel.js +117 -0
  232. package/dist/panels/inspector/styles/box-model.d.ts +20 -0
  233. package/dist/panels/inspector/styles/box-model.d.ts.map +1 -0
  234. package/dist/panels/inspector/styles/box-model.js +31 -0
  235. package/dist/panels/inspector/styles/index.d.ts +5 -0
  236. package/dist/panels/inspector/styles/index.d.ts.map +1 -0
  237. package/dist/panels/inspector/styles/index.js +2 -0
  238. package/dist/panels/inspector/styles/model.d.ts +55 -0
  239. package/dist/panels/inspector/styles/model.d.ts.map +1 -0
  240. package/dist/panels/inspector/styles/model.js +111 -0
  241. package/dist/panels/inspector/styles/segments.d.ts +18 -0
  242. package/dist/panels/inspector/styles/segments.d.ts.map +1 -0
  243. package/dist/panels/inspector/styles/segments.js +75 -0
  244. package/dist/panels/inspector/styles/sides-editor.d.ts +34 -0
  245. package/dist/panels/inspector/styles/sides-editor.d.ts.map +1 -0
  246. package/dist/panels/inspector/styles/sides-editor.js +86 -0
  247. package/dist/panels/inspector/styles/style-inspector.d.ts +15 -0
  248. package/dist/panels/inspector/styles/style-inspector.d.ts.map +1 -0
  249. package/dist/panels/inspector/styles/style-inspector.js +219 -0
  250. package/dist/panels/inspector/styles/style-inspector.test.d.ts +2 -0
  251. package/dist/panels/inspector/styles/style-inspector.test.d.ts.map +1 -0
  252. package/dist/panels/inspector/styles/style-inspector.test.js +265 -0
  253. package/dist/panels/inspector/styles/token-picker.d.ts +15 -0
  254. package/dist/panels/inspector/styles/token-picker.d.ts.map +1 -0
  255. package/dist/panels/inspector/styles/token-picker.js +23 -0
  256. package/dist/panels/inspector/styles/use-style-value.d.ts +28 -0
  257. package/dist/panels/inspector/styles/use-style-value.d.ts.map +1 -0
  258. package/dist/panels/inspector/styles/use-style-value.js +51 -0
  259. package/dist/panels/inspector/value.d.ts +20 -0
  260. package/dist/panels/inspector/value.d.ts.map +1 -0
  261. package/dist/panels/inspector/value.js +32 -0
  262. package/dist/panels/inspector/values/analyze.d.ts +49 -0
  263. package/dist/panels/inspector/values/analyze.d.ts.map +1 -0
  264. package/dist/panels/inspector/values/analyze.js +115 -0
  265. package/dist/panels/inspector/values/data.d.ts +18 -0
  266. package/dist/panels/inspector/values/data.d.ts.map +1 -0
  267. package/dist/panels/inspector/values/data.js +10 -0
  268. package/dist/panels/inspector/values/translation.d.ts +20 -0
  269. package/dist/panels/inspector/values/translation.d.ts.map +1 -0
  270. package/dist/panels/inspector/values/translation.js +25 -0
  271. package/dist/panels/inspector/values/value-editor.d.ts +30 -0
  272. package/dist/panels/inspector/values/value-editor.d.ts.map +1 -0
  273. package/dist/panels/inspector/values/value-editor.js +191 -0
  274. package/dist/panels/inspector/values/values.test.d.ts +2 -0
  275. package/dist/panels/inspector/values/values.test.d.ts.map +1 -0
  276. package/dist/panels/inspector/values/values.test.js +173 -0
  277. package/dist/panels/issues/collect.d.ts +70 -0
  278. package/dist/panels/issues/collect.d.ts.map +1 -0
  279. package/dist/panels/issues/collect.js +96 -0
  280. package/dist/panels/issues/index.d.ts +5 -0
  281. package/dist/panels/issues/index.d.ts.map +1 -0
  282. package/dist/panels/issues/index.js +2 -0
  283. package/dist/panels/issues/issues-panel.d.ts +17 -0
  284. package/dist/panels/issues/issues-panel.d.ts.map +1 -0
  285. package/dist/panels/issues/issues-panel.js +77 -0
  286. package/dist/panels/layers/flatten.d.ts +28 -0
  287. package/dist/panels/layers/flatten.d.ts.map +1 -0
  288. package/dist/panels/layers/flatten.js +61 -0
  289. package/dist/panels/layers/layers-panel.d.ts +14 -0
  290. package/dist/panels/layers/layers-panel.d.ts.map +1 -0
  291. package/dist/panels/layers/layers-panel.js +428 -0
  292. package/dist/panels/layers/layers-panel.test.d.ts +2 -0
  293. package/dist/panels/layers/layers-panel.test.d.ts.map +1 -0
  294. package/dist/panels/layers/layers-panel.test.js +315 -0
  295. package/dist/persistence/controller.d.ts +55 -0
  296. package/dist/persistence/controller.d.ts.map +1 -0
  297. package/dist/persistence/controller.js +341 -0
  298. package/dist/persistence/index.d.ts +6 -0
  299. package/dist/persistence/index.d.ts.map +1 -0
  300. package/dist/persistence/index.js +3 -0
  301. package/dist/persistence/load.d.ts +35 -0
  302. package/dist/persistence/load.d.ts.map +1 -0
  303. package/dist/persistence/load.js +67 -0
  304. package/dist/persistence/persistence.test.d.ts +2 -0
  305. package/dist/persistence/persistence.test.d.ts.map +1 -0
  306. package/dist/persistence/persistence.test.js +483 -0
  307. package/dist/persistence/react.d.ts +18 -0
  308. package/dist/persistence/react.d.ts.map +1 -0
  309. package/dist/persistence/react.js +105 -0
  310. package/dist/persistence/types.d.ts +182 -0
  311. package/dist/persistence/types.d.ts.map +1 -0
  312. package/dist/persistence/types.js +1 -0
  313. package/dist/preview/index.d.ts +3 -0
  314. package/dist/preview/index.d.ts.map +1 -0
  315. package/dist/preview/index.js +2 -0
  316. package/dist/preview/prepare.d.ts +16 -0
  317. package/dist/preview/prepare.d.ts.map +1 -0
  318. package/dist/preview/prepare.js +21 -0
  319. package/dist/preview/preview.d.ts +27 -0
  320. package/dist/preview/preview.d.ts.map +1 -0
  321. package/dist/preview/preview.js +51 -0
  322. package/dist/preview/preview.test.d.ts +2 -0
  323. package/dist/preview/preview.test.d.ts.map +1 -0
  324. package/dist/preview/preview.test.js +129 -0
  325. package/dist/shortcuts/actions.d.ts +17 -0
  326. package/dist/shortcuts/actions.d.ts.map +1 -0
  327. package/dist/shortcuts/actions.js +85 -0
  328. package/dist/shortcuts/index.d.ts +11 -0
  329. package/dist/shortcuts/index.d.ts.map +1 -0
  330. package/dist/shortcuts/index.js +5 -0
  331. package/dist/shortcuts/keys.d.ts +29 -0
  332. package/dist/shortcuts/keys.d.ts.map +1 -0
  333. package/dist/shortcuts/keys.js +100 -0
  334. package/dist/shortcuts/map.d.ts +17 -0
  335. package/dist/shortcuts/map.d.ts.map +1 -0
  336. package/dist/shortcuts/map.js +31 -0
  337. package/dist/shortcuts/registry.d.ts +32 -0
  338. package/dist/shortcuts/registry.d.ts.map +1 -0
  339. package/dist/shortcuts/registry.js +53 -0
  340. package/dist/shortcuts/shortcuts.d.ts +32 -0
  341. package/dist/shortcuts/shortcuts.d.ts.map +1 -0
  342. package/dist/shortcuts/shortcuts.js +95 -0
  343. package/dist/shortcuts/shortcuts.test.d.ts +2 -0
  344. package/dist/shortcuts/shortcuts.test.d.ts.map +1 -0
  345. package/dist/shortcuts/shortcuts.test.js +263 -0
  346. package/dist/store/create-store.d.ts +13 -0
  347. package/dist/store/create-store.d.ts.map +1 -0
  348. package/dist/store/create-store.js +248 -0
  349. package/dist/store/index.d.ts +9 -0
  350. package/dist/store/index.d.ts.map +1 -0
  351. package/dist/store/index.js +5 -0
  352. package/dist/store/locale.d.ts +23 -0
  353. package/dist/store/locale.d.ts.map +1 -0
  354. package/dist/store/locale.js +31 -0
  355. package/dist/store/react.d.ts +17 -0
  356. package/dist/store/react.d.ts.map +1 -0
  357. package/dist/store/react.js +32 -0
  358. package/dist/store/selection.d.ts +32 -0
  359. package/dist/store/selection.d.ts.map +1 -0
  360. package/dist/store/selection.js +84 -0
  361. package/dist/store/selection.test.d.ts +2 -0
  362. package/dist/store/selection.test.d.ts.map +1 -0
  363. package/dist/store/selection.test.js +95 -0
  364. package/dist/store/selectors.d.ts +18 -0
  365. package/dist/store/selectors.d.ts.map +1 -0
  366. package/dist/store/selectors.js +39 -0
  367. package/dist/store/store.test.d.ts +2 -0
  368. package/dist/store/store.test.d.ts.map +1 -0
  369. package/dist/store/store.test.js +331 -0
  370. package/dist/store/types.d.ts +114 -0
  371. package/dist/store/types.d.ts.map +1 -0
  372. package/dist/store/types.js +1 -0
  373. package/dist/styles/tokens.test.d.ts +2 -0
  374. package/dist/styles/tokens.test.d.ts.map +1 -0
  375. package/dist/styles/tokens.test.js +199 -0
  376. package/dist/styles.css +2885 -0
  377. package/dist/toolbar/brand.d.ts +7 -0
  378. package/dist/toolbar/brand.d.ts.map +1 -0
  379. package/dist/toolbar/brand.js +11 -0
  380. package/dist/toolbar/breakpoint-control.d.ts +9 -0
  381. package/dist/toolbar/breakpoint-control.d.ts.map +1 -0
  382. package/dist/toolbar/breakpoint-control.js +23 -0
  383. package/dist/toolbar/editable-title.d.ts +14 -0
  384. package/dist/toolbar/editable-title.d.ts.map +1 -0
  385. package/dist/toolbar/editable-title.js +46 -0
  386. package/dist/toolbar/editable-title.test.d.ts +2 -0
  387. package/dist/toolbar/editable-title.test.d.ts.map +1 -0
  388. package/dist/toolbar/editable-title.test.js +53 -0
  389. package/dist/toolbar/index.d.ts +12 -0
  390. package/dist/toolbar/index.d.ts.map +1 -0
  391. package/dist/toolbar/index.js +5 -0
  392. package/dist/toolbar/locale-switcher.d.ts +10 -0
  393. package/dist/toolbar/locale-switcher.d.ts.map +1 -0
  394. package/dist/toolbar/locale-switcher.js +20 -0
  395. package/dist/toolbar/more-menu.d.ts +12 -0
  396. package/dist/toolbar/more-menu.d.ts.map +1 -0
  397. package/dist/toolbar/more-menu.js +47 -0
  398. package/dist/toolbar/panel-toggles.d.ts +9 -0
  399. package/dist/toolbar/panel-toggles.d.ts.map +1 -0
  400. package/dist/toolbar/panel-toggles.js +19 -0
  401. package/dist/toolbar/publish-dialog.d.ts +18 -0
  402. package/dist/toolbar/publish-dialog.d.ts.map +1 -0
  403. package/dist/toolbar/publish-dialog.js +49 -0
  404. package/dist/toolbar/publish.test.d.ts +2 -0
  405. package/dist/toolbar/publish.test.d.ts.map +1 -0
  406. package/dist/toolbar/publish.test.js +258 -0
  407. package/dist/toolbar/sample-picker.d.ts +18 -0
  408. package/dist/toolbar/sample-picker.d.ts.map +1 -0
  409. package/dist/toolbar/sample-picker.js +72 -0
  410. package/dist/toolbar/sample-picker.test.d.ts +2 -0
  411. package/dist/toolbar/sample-picker.test.d.ts.map +1 -0
  412. package/dist/toolbar/sample-picker.test.js +78 -0
  413. package/dist/toolbar/save-indicator.d.ts +8 -0
  414. package/dist/toolbar/save-indicator.d.ts.map +1 -0
  415. package/dist/toolbar/save-indicator.js +30 -0
  416. package/dist/toolbar/theme.d.ts +22 -0
  417. package/dist/toolbar/theme.d.ts.map +1 -0
  418. package/dist/toolbar/theme.js +46 -0
  419. package/dist/toolbar/theme.test.d.ts +2 -0
  420. package/dist/toolbar/theme.test.d.ts.map +1 -0
  421. package/dist/toolbar/theme.test.js +49 -0
  422. package/dist/toolbar/toolbar-centre.d.ts +13 -0
  423. package/dist/toolbar/toolbar-centre.d.ts.map +1 -0
  424. package/dist/toolbar/toolbar-centre.js +7 -0
  425. package/dist/toolbar/toolbar-left.d.ts +12 -0
  426. package/dist/toolbar/toolbar-left.d.ts.map +1 -0
  427. package/dist/toolbar/toolbar-left.js +16 -0
  428. package/dist/toolbar/toolbar-right.d.ts +19 -0
  429. package/dist/toolbar/toolbar-right.d.ts.map +1 -0
  430. package/dist/toolbar/toolbar-right.js +21 -0
  431. package/dist/toolbar/toolbar.d.ts +38 -0
  432. package/dist/toolbar/toolbar.d.ts.map +1 -0
  433. package/dist/toolbar/toolbar.js +27 -0
  434. package/dist/toolbar/toolbar.test.d.ts +2 -0
  435. package/dist/toolbar/toolbar.test.d.ts.map +1 -0
  436. package/dist/toolbar/toolbar.test.js +289 -0
  437. package/dist/toolbar/use-overflow-level.d.ts +9 -0
  438. package/dist/toolbar/use-overflow-level.d.ts.map +1 -0
  439. package/dist/toolbar/use-overflow-level.js +40 -0
  440. package/dist/toolbar/zoom-menu.d.ts +10 -0
  441. package/dist/toolbar/zoom-menu.d.ts.map +1 -0
  442. package/dist/toolbar/zoom-menu.js +17 -0
  443. package/dist/ui/icon.d.ts +102 -0
  444. package/dist/ui/icon.d.ts.map +1 -0
  445. package/dist/ui/icon.js +182 -0
  446. package/dist/ui/icon.test.d.ts +2 -0
  447. package/dist/ui/icon.test.d.ts.map +1 -0
  448. package/dist/ui/icon.test.js +115 -0
  449. package/dist/ui/index.d.ts +11 -0
  450. package/dist/ui/index.d.ts.map +1 -0
  451. package/dist/ui/index.js +5 -0
  452. package/dist/ui/panel.d.ts +18 -0
  453. package/dist/ui/panel.d.ts.map +1 -0
  454. package/dist/ui/panel.js +21 -0
  455. package/dist/ui/portal.d.ts +14 -0
  456. package/dist/ui/portal.d.ts.map +1 -0
  457. package/dist/ui/portal.js +14 -0
  458. package/dist/ui/primitives.d.ts +190 -0
  459. package/dist/ui/primitives.d.ts.map +1 -0
  460. package/dist/ui/primitives.js +164 -0
  461. package/dist/ui/primitives.test.d.ts +2 -0
  462. package/dist/ui/primitives.test.d.ts.map +1 -0
  463. package/dist/ui/primitives.test.js +215 -0
  464. package/dist/ui/toast.d.ts +39 -0
  465. package/dist/ui/toast.d.ts.map +1 -0
  466. package/dist/ui/toast.js +76 -0
  467. package/dist/ui/toast.test.d.ts +2 -0
  468. package/dist/ui/toast.test.d.ts.map +1 -0
  469. package/dist/ui/toast.test.js +95 -0
  470. package/package.json +66 -3
  471. package/README.md +0 -3
@@ -0,0 +1,100 @@
1
+ export function detectPlatform(navigatorLike = typeof navigator === 'undefined' ? undefined : navigator) {
2
+ const text = `${navigatorLike?.platform ?? ''} ${navigatorLike?.userAgent ?? ''}`;
3
+ return /mac|iphone|ipad/i.test(text) ? 'mac' : 'other';
4
+ }
5
+ const KEY_ALIASES = {
6
+ ' ': 'space',
7
+ esc: 'escape',
8
+ del: 'delete',
9
+ up: 'arrowup',
10
+ down: 'arrowdown',
11
+ left: 'arrowleft',
12
+ right: 'arrowright',
13
+ };
14
+ const MODIFIER_ORDER = ['mod', 'ctrl', 'meta', 'alt', 'shift'];
15
+ /**
16
+ * The canonical text of a combination: modifiers in a fixed order (`mod` is Cmd on a Mac and Ctrl
17
+ * elsewhere), then the key, all lower case — `mod+shift+z`, `alt+arrowup`, `delete`. Two spellings
18
+ * of one combination give the same text, so a lookup is a plain string comparison.
19
+ */
20
+ export function normalizeCombo(spec) {
21
+ const parts = spec
22
+ .toLowerCase()
23
+ .split('+')
24
+ .map((part) => part.trim())
25
+ .filter((part) => part !== '');
26
+ // "shift++" style specs are not supported; a "+" key is written "plus".
27
+ const key = parts.pop() ?? '';
28
+ const mods = MODIFIER_ORDER.filter((mod) => parts.includes(mod));
29
+ return [...mods, KEY_ALIASES[key] ?? key].join('+');
30
+ }
31
+ /** The canonical combination of a key press on `platform`. */
32
+ export function comboOf(input, platform) {
33
+ const primary = platform === 'mac' ? input.mods.meta : input.mods.ctrl;
34
+ const other = platform === 'mac' ? input.mods.ctrl : input.mods.meta;
35
+ const parts = [];
36
+ if (primary)
37
+ parts.push('mod');
38
+ if (other)
39
+ parts.push(platform === 'mac' ? 'ctrl' : 'meta');
40
+ if (input.mods.alt)
41
+ parts.push('alt');
42
+ if (input.mods.shift)
43
+ parts.push('shift');
44
+ const key = input.key.toLowerCase();
45
+ parts.push(KEY_ALIASES[key] ?? key);
46
+ return parts.join('+');
47
+ }
48
+ const SYMBOLS_MAC = {
49
+ mod: '⌘',
50
+ ctrl: '⌃',
51
+ alt: '⌥',
52
+ shift: '⇧',
53
+ meta: '⌘',
54
+ arrowup: '↑',
55
+ arrowdown: '↓',
56
+ arrowleft: '←',
57
+ arrowright: '→',
58
+ delete: '⌫',
59
+ backspace: '⌫',
60
+ escape: 'Esc',
61
+ };
62
+ const WORDS = {
63
+ mod: 'Ctrl',
64
+ ctrl: 'Ctrl',
65
+ meta: 'Meta',
66
+ alt: 'Alt',
67
+ shift: 'Shift',
68
+ arrowup: '↑',
69
+ arrowdown: '↓',
70
+ arrowleft: '←',
71
+ arrowright: '→',
72
+ delete: 'Del',
73
+ backspace: 'Backspace',
74
+ escape: 'Esc',
75
+ };
76
+ const capital = (text) => text.charAt(0).toUpperCase() + text.slice(1);
77
+ /** How a combination is shown to the author on `platform` (`⌘⇧Z`, `Ctrl+Shift+Z`). */
78
+ export function displayCombo(combo, platform) {
79
+ const parts = combo.split('+');
80
+ if (platform === 'mac') {
81
+ return parts.map((part) => SYMBOLS_MAC[part] ?? part.toUpperCase()).join('');
82
+ }
83
+ return parts.map((part) => WORDS[part] ?? capital(part)).join('+');
84
+ }
85
+ /** The keyboard belongs to text here: a field, a select or an editable region. */
86
+ export function isTypingTarget(target) {
87
+ const element = target;
88
+ if (element === null || typeof element.tagName !== 'string')
89
+ return false;
90
+ const tag = element.tagName.toLowerCase();
91
+ if (tag === 'input') {
92
+ const type = element.type ?? 'text';
93
+ return !['checkbox', 'radio', 'button', 'submit', 'reset', 'range', 'color'].includes(type);
94
+ }
95
+ if (tag === 'textarea' || tag === 'select')
96
+ return true;
97
+ if (element.isContentEditable === true)
98
+ return true;
99
+ return element.closest?.('[contenteditable="true"], [role="textbox"]') != null;
100
+ }
@@ -0,0 +1,17 @@
1
+ import type { MessageKey } from '../messages/index.tsx';
2
+ export interface ShortcutDef {
3
+ readonly action: string;
4
+ readonly label: MessageKey;
5
+ readonly group: 'edit' | 'selection' | 'file' | 'help';
6
+ /** Canonical combinations (`mod+z`); the first is the one the help dialog shows first. */
7
+ readonly keys: readonly string[];
8
+ }
9
+ /** The shortcuts of the MVP (docs/editor.md#keyboard-shortcuts-pb-084). */
10
+ export declare const DEFAULT_SHORTCUTS: readonly ShortcutDef[];
11
+ /**
12
+ * The map with the host's overrides applied (`config.shortcuts`, by action id): an override
13
+ * replaces the action's combinations with that one; an empty string turns the action's shortcut
14
+ * off. Overrides for unknown actions are ignored.
15
+ */
16
+ export declare function applyOverrides(defaults: readonly ShortcutDef[], overrides: Readonly<Record<string, string>>): ShortcutDef[];
17
+ //# sourceMappingURL=map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../../src/shortcuts/map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGxD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;IACvD,0FAA0F;IAC1F,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AASD,2EAA2E;AAC3E,eAAO,MAAM,iBAAiB,EAAE,SAAS,WAAW,EAcnD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,SAAS,WAAW,EAAE,EAChC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAC1C,WAAW,EAAE,CAMf"}
@@ -0,0 +1,31 @@
1
+ import { normalizeCombo } from './keys.js';
2
+ const def = (action, label, group, ...keys) => ({ action, label, group, keys: keys.map(normalizeCombo) });
3
+ /** The shortcuts of the MVP (docs/editor.md#keyboard-shortcuts-pb-084). */
4
+ export const DEFAULT_SHORTCUTS = [
5
+ def('edit.undo', 'shortcut.undo', 'edit', 'mod+z'),
6
+ def('edit.redo', 'shortcut.redo', 'edit', 'mod+shift+z', 'mod+y'),
7
+ def('edit.copy', 'shortcut.copy', 'edit', 'mod+c'),
8
+ def('edit.cut', 'shortcut.cut', 'edit', 'mod+x'),
9
+ def('edit.paste', 'shortcut.paste', 'edit', 'mod+v'),
10
+ def('edit.duplicate', 'shortcut.duplicate', 'edit', 'mod+d'),
11
+ def('edit.delete', 'shortcut.delete', 'edit', 'delete', 'backspace'),
12
+ def('node.moveUp', 'shortcut.moveUp', 'edit', 'alt+arrowup'),
13
+ def('node.moveDown', 'shortcut.moveDown', 'edit', 'alt+arrowdown'),
14
+ def('selection.all', 'shortcut.selectAll', 'selection', 'mod+a'),
15
+ def('selection.clear', 'shortcut.clearSelection', 'selection', 'escape'),
16
+ def('file.save', 'shortcut.save', 'file', 'mod+s'),
17
+ def('help.shortcuts', 'shortcut.help', 'help', 'shift+?'),
18
+ ];
19
+ /**
20
+ * The map with the host's overrides applied (`config.shortcuts`, by action id): an override
21
+ * replaces the action's combinations with that one; an empty string turns the action's shortcut
22
+ * off. Overrides for unknown actions are ignored.
23
+ */
24
+ export function applyOverrides(defaults, overrides) {
25
+ return defaults.map((shortcut) => {
26
+ if (!Object.hasOwn(overrides, shortcut.action))
27
+ return shortcut;
28
+ const combo = normalizeCombo(overrides[shortcut.action] ?? '');
29
+ return { ...shortcut, keys: combo === '' ? [] : [combo] };
30
+ });
31
+ }
@@ -0,0 +1,32 @@
1
+ import { type KeyInput, type Platform } from './keys.ts';
2
+ import { type ShortcutDef } from './map.ts';
3
+ /** A handler returns `false` when it did nothing, so the key keeps its default behaviour. */
4
+ export type ShortcutHandler = () => boolean | undefined;
5
+ export interface ShortcutRegistryOptions {
6
+ readonly platform: Platform;
7
+ readonly shortcuts?: readonly ShortcutDef[];
8
+ readonly overrides?: Readonly<Record<string, string>>;
9
+ }
10
+ export interface ShortcutRegistry {
11
+ readonly platform: Platform;
12
+ readonly shortcuts: readonly ShortcutDef[];
13
+ /**
14
+ * Attaches `handler` to an action in `scope` (`'editor'` unless said otherwise). Returns the
15
+ * function that removes it.
16
+ */
17
+ bind(action: string, handler: ShortcutHandler, scope?: string): () => void;
18
+ /** The scopes whose bindings fire; `['editor']` at first. A modal dialog narrows it to its own. */
19
+ setScopes(scopes: readonly string[]): void;
20
+ /**
21
+ * Runs the handler of the shortcut `input` is, and says whether one ran. Nothing runs while
22
+ * `typing` (the focus is in a text field): there the keys belong to the text.
23
+ */
24
+ handle(input: KeyInput, options: {
25
+ readonly typing: boolean;
26
+ }): boolean;
27
+ /** The combinations of an action, canonical (`mod+z`). */
28
+ keysFor(action: string): readonly string[];
29
+ }
30
+ /** A shortcut registry of its own — nothing here is shared between editors (no global state). */
31
+ export declare function createShortcutRegistry(options: ShortcutRegistryOptions): ShortcutRegistry;
32
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/shortcuts/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EAAqC,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAE/E,6FAA6F;AAC7F,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,GAAG,SAAS,CAAC;AAExD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IAC5C,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACvD;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,SAAS,WAAW,EAAE,CAAC;IAC3C;;;OAGG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;IAC3E,mGAAmG;IACnG,SAAS,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAC3C;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC;IACxE,0DAA0D;IAC1D,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED,iGAAiG;AACjG,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,gBAAgB,CA6CzF"}
@@ -0,0 +1,53 @@
1
+ import { comboOf } from './keys.js';
2
+ import { applyOverrides, DEFAULT_SHORTCUTS } from './map.js';
3
+ /** A shortcut registry of its own — nothing here is shared between editors (no global state). */
4
+ export function createShortcutRegistry(options) {
5
+ const shortcuts = applyOverrides(options.shortcuts ?? DEFAULT_SHORTCUTS, options.overrides ?? {});
6
+ const actionOf = new Map();
7
+ for (const shortcut of shortcuts) {
8
+ // A combination belongs to the first action that claims it.
9
+ for (const combo of shortcut.keys)
10
+ if (!actionOf.has(combo))
11
+ actionOf.set(combo, shortcut.action);
12
+ }
13
+ const bindings = new Map();
14
+ let scopes = ['editor'];
15
+ return {
16
+ platform: options.platform,
17
+ shortcuts,
18
+ bind(action, handler, scope = 'editor') {
19
+ const entry = { handler, scope };
20
+ const list = bindings.get(action) ?? [];
21
+ list.push(entry);
22
+ bindings.set(action, list);
23
+ return () => {
24
+ const current = bindings.get(action) ?? [];
25
+ const at = current.indexOf(entry);
26
+ if (at !== -1)
27
+ current.splice(at, 1);
28
+ };
29
+ },
30
+ setScopes(next) {
31
+ scopes = [...next];
32
+ },
33
+ handle(input, { typing }) {
34
+ if (typing)
35
+ return false;
36
+ const action = actionOf.get(comboOf(input, options.platform));
37
+ if (action === undefined)
38
+ return false;
39
+ // The most recent binding in an active scope wins, as a dialog's handler should over the editor's.
40
+ const list = bindings.get(action) ?? [];
41
+ for (let at = list.length - 1; at >= 0; at--) {
42
+ const entry = list[at];
43
+ if (entry === undefined || !scopes.includes(entry.scope))
44
+ continue;
45
+ return entry.handler() !== false;
46
+ }
47
+ return false;
48
+ },
49
+ keysFor(action) {
50
+ return shortcuts.find((shortcut) => shortcut.action === action)?.keys ?? [];
51
+ },
52
+ };
53
+ }
@@ -0,0 +1,32 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type ExternalActions } from './actions.ts';
3
+ import { type KeyInput, type Platform } from './keys.ts';
4
+ import { type ShortcutRegistry } from './registry.ts';
5
+ /** The registry of the enclosing `<ShortcutProvider>`, or `undefined` outside one (a toolbar shown without shortcuts). */
6
+ export declare function useOptionalShortcutRegistry(): ShortcutRegistry | undefined;
7
+ /** The registry of the enclosing `<ShortcutProvider>`, for modules that bind actions of their own. */
8
+ export declare function useShortcutRegistry(): ShortcutRegistry;
9
+ /**
10
+ * What the canvas host's `onKeyDown` should call with a forwarded `key:down`. The canvas already
11
+ * keeps text fields and inline edits to itself, so a forwarded key is never "typing". Returns
12
+ * whether a shortcut took it.
13
+ */
14
+ export declare function useForwardedKeys(): (input: KeyInput) => boolean;
15
+ export interface ShortcutProviderProps {
16
+ /** Overrides by action id (`config.shortcuts`). */
17
+ readonly overrides?: Readonly<Record<string, string>>;
18
+ /** The actions other modules provide: clipboard (PB-085) and save (PB-087). */
19
+ readonly actions?: ExternalActions;
20
+ readonly platform?: Platform;
21
+ readonly children: ReactNode;
22
+ }
23
+ /**
24
+ * Keyboard shortcuts for the editor (docs/editor.md#keyboard-shortcuts-pb-084): a registry, the
25
+ * store's actions bound to it, a `keydown` listener on the document, and the help dialog (`?`).
26
+ * A key press whose focus is in a text field is never handled, and a handled one gets
27
+ * `preventDefault`, so the browser does not also act on it.
28
+ */
29
+ export declare function ShortcutProvider({ overrides, actions, platform, children, }: ShortcutProviderProps): import("react").JSX.Element;
30
+ /** How the first key of `action` is written on this platform (`Ctrl+Z`), for tooltips; `undefined` when it has none. */
31
+ export declare function useShortcutHint(action: string): string | undefined;
32
+ //# sourceMappingURL=shortcuts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortcuts.d.ts","sourceRoot":"","sources":["../../src/shortcuts/shortcuts.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EAMf,MAAM,OAAO,CAAC;AAIf,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAIL,KAAK,QAAQ,EACb,KAAK,QAAQ,EACd,MAAM,WAAW,CAAC;AACnB,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAI9E,0HAA0H;AAC1H,wBAAgB,2BAA2B,IAAI,gBAAgB,GAAG,SAAS,CAE1E;AAED,sGAAsG;AACtG,wBAAgB,mBAAmB,IAAI,gBAAgB,CAMtD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,CAAC,KAAK,EAAE,QAAQ,KAAK,OAAO,CAG/D;AAED,MAAM,WAAW,qBAAqB;IACpC,mDAAmD;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AAOD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,OAAO,EACP,QAAQ,EACR,QAAQ,GACT,EAAE,qBAAqB,+BAkFvB;AAED,wHAAwH;AACxH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMlE"}
@@ -0,0 +1,95 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { createContext, useContext, useEffect, useMemo, useRef, useState, } from 'react';
3
+ import { useT } from '../messages/index.js';
4
+ import { useEditor } from '../store/index.js';
5
+ import { Dialog } from '../ui/index.js';
6
+ import { bindEditorActions } from './actions.js';
7
+ import { detectPlatform, displayCombo, isTypingTarget, } from './keys.js';
8
+ import { createShortcutRegistry } from './registry.js';
9
+ const RegistryContext = createContext(undefined);
10
+ /** The registry of the enclosing `<ShortcutProvider>`, or `undefined` outside one (a toolbar shown without shortcuts). */
11
+ export function useOptionalShortcutRegistry() {
12
+ return useContext(RegistryContext);
13
+ }
14
+ /** The registry of the enclosing `<ShortcutProvider>`, for modules that bind actions of their own. */
15
+ export function useShortcutRegistry() {
16
+ const registry = useContext(RegistryContext);
17
+ if (registry === undefined) {
18
+ throw new Error('useShortcutRegistry must be used inside <ShortcutProvider>');
19
+ }
20
+ return registry;
21
+ }
22
+ /**
23
+ * What the canvas host's `onKeyDown` should call with a forwarded `key:down`. The canvas already
24
+ * keeps text fields and inline edits to itself, so a forwarded key is never "typing". Returns
25
+ * whether a shortcut took it.
26
+ */
27
+ export function useForwardedKeys() {
28
+ const registry = useShortcutRegistry();
29
+ return (input) => registry.handle(input, { typing: false });
30
+ }
31
+ const toInput = (event) => ({
32
+ key: event.key,
33
+ mods: { shift: event.shiftKey, alt: event.altKey, ctrl: event.ctrlKey, meta: event.metaKey },
34
+ });
35
+ /**
36
+ * Keyboard shortcuts for the editor (docs/editor.md#keyboard-shortcuts-pb-084): a registry, the
37
+ * store's actions bound to it, a `keydown` listener on the document, and the help dialog (`?`).
38
+ * A key press whose focus is in a text field is never handled, and a handled one gets
39
+ * `preventDefault`, so the browser does not also act on it.
40
+ */
41
+ export function ShortcutProvider({ overrides, actions, platform, children, }) {
42
+ const store = useEditor();
43
+ const t = useT();
44
+ const [helpOpen, setHelpOpen] = useState(false);
45
+ const detected = useMemo(() => platform ?? detectPlatform(), [platform]);
46
+ const registry = useMemo(() => createShortcutRegistry({ platform: detected, overrides: overrides ?? {} }), [detected, overrides]);
47
+ // The handlers read the latest actions without rebinding on every render.
48
+ const external = useRef({});
49
+ external.current = actions ?? {};
50
+ useEffect(() => {
51
+ const unbind = bindEditorActions(registry, store, {
52
+ copy: () => external.current.copy?.() ?? false,
53
+ cut: () => external.current.cut?.() ?? false,
54
+ paste: () => external.current.paste?.() ?? false,
55
+ save: () => external.current.save?.() ?? false,
56
+ });
57
+ const unbindHelp = registry.bind('help.shortcuts', () => {
58
+ setHelpOpen(true);
59
+ return true;
60
+ });
61
+ return () => {
62
+ unbind();
63
+ unbindHelp();
64
+ };
65
+ }, [registry, store]);
66
+ useEffect(() => {
67
+ registry.setScopes(helpOpen ? ['dialog'] : ['editor']);
68
+ }, [registry, helpOpen]);
69
+ useEffect(() => {
70
+ const onKeyDown = (event) => {
71
+ if (event.defaultPrevented || event.isComposing)
72
+ return;
73
+ const handled = registry.handle(toInput(event), { typing: isTypingTarget(event.target) });
74
+ if (handled)
75
+ event.preventDefault();
76
+ };
77
+ document.addEventListener('keydown', onKeyDown);
78
+ return () => document.removeEventListener('keydown', onKeyDown);
79
+ }, [registry]);
80
+ const groups = ['edit', 'selection', 'file', 'help'].map((group) => ({
81
+ group,
82
+ items: registry.shortcuts.filter((shortcut) => shortcut.group === group && shortcut.keys.length > 0),
83
+ }));
84
+ return (_jsxs(RegistryContext.Provider, { value: registry, children: [children, _jsx(Dialog, { open: helpOpen, onOpenChange: setHelpOpen, title: t('shortcut.title'), children: _jsx("div", { className: "bd-shortcut-help", children: groups
85
+ .filter(({ items }) => items.length > 0)
86
+ .map(({ group, items }) => (_jsxs("section", { children: [_jsx("h4", { children: t(`shortcut.group.${group}`) }), _jsx("dl", { children: items.map((shortcut) => (_jsxs("div", { className: "bd-shortcut-row", children: [_jsx("dt", { children: t(shortcut.label) }), _jsx("dd", { children: shortcut.keys.map((combo, index) => (_jsxs("span", { children: [index > 0 ? ' / ' : '', _jsx("kbd", { children: displayCombo(combo, detected) })] }, combo))) })] }, shortcut.action))) })] }, group))) }) })] }));
87
+ }
88
+ /** How the first key of `action` is written on this platform (`Ctrl+Z`), for tooltips; `undefined` when it has none. */
89
+ export function useShortcutHint(action) {
90
+ const registry = useOptionalShortcutRegistry();
91
+ const combo = registry?.keysFor(action)[0];
92
+ return registry === undefined || combo === undefined
93
+ ? undefined
94
+ : displayCombo(combo, registry.platform);
95
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=shortcuts.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortcuts.test.d.ts","sourceRoot":"","sources":["../../src/shortcuts/shortcuts.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,263 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // @vitest-environment jsdom
3
+ import { createRegistryMeta, createSeededIdGenerator, } from '@next-buildr/core';
4
+ import { act } from 'react';
5
+ import { createRoot } from 'react-dom/client';
6
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
7
+ import { MessagesProvider } from '../messages/index.js';
8
+ import { createEditorStore, EditorStoreProvider } from '../store/index.js';
9
+ import { comboOf, displayCombo, isTypingTarget, normalizeCombo } from './keys.js';
10
+ import { DEFAULT_SHORTCUTS } from './map.js';
11
+ import { createShortcutRegistry } from './registry.js';
12
+ import { ShortcutProvider, useForwardedKeys } from './shortcuts.js';
13
+ globalThis.IS_REACT_ACT_ENVIRONMENT = true;
14
+ const none = { shift: false, alt: false, ctrl: false, meta: false };
15
+ const press = (key, mods = {}) => ({
16
+ key,
17
+ mods: { ...none, ...mods },
18
+ });
19
+ describe('combinations', () => {
20
+ it('normalizes spellings of one combination to the same text', () => {
21
+ expect(normalizeCombo('Shift+Mod+Z')).toBe('mod+shift+z');
22
+ expect(normalizeCombo('Del')).toBe('delete');
23
+ expect(normalizeCombo('alt+Up')).toBe('alt+arrowup');
24
+ });
25
+ it('reads Cmd as the primary key on a Mac and Ctrl elsewhere', () => {
26
+ expect(comboOf(press('z', { meta: true }), 'mac')).toBe('mod+z');
27
+ expect(comboOf(press('z', { ctrl: true }), 'mac')).toBe('ctrl+z');
28
+ expect(comboOf(press('z', { ctrl: true }), 'other')).toBe('mod+z');
29
+ expect(comboOf(press('Z', { ctrl: true, shift: true }), 'other')).toBe('mod+shift+z');
30
+ });
31
+ it('shows them the way the platform writes them', () => {
32
+ expect(displayCombo('mod+shift+z', 'mac')).toBe('⌘⇧Z');
33
+ expect(displayCombo('mod+shift+z', 'other')).toBe('Ctrl+Shift+Z');
34
+ });
35
+ it('knows where the keyboard belongs to text', () => {
36
+ const input = document.createElement('input');
37
+ const box = document.createElement('input');
38
+ box.type = 'checkbox';
39
+ const editable = document.createElement('div');
40
+ editable.setAttribute('role', 'textbox');
41
+ const inner = document.createElement('span');
42
+ editable.append(inner);
43
+ expect(isTypingTarget(input)).toBe(true);
44
+ expect(isTypingTarget(document.createElement('textarea'))).toBe(true);
45
+ expect(isTypingTarget(inner)).toBe(true);
46
+ expect(isTypingTarget(box)).toBe(false);
47
+ expect(isTypingTarget(document.createElement('button'))).toBe(false);
48
+ expect(isTypingTarget(null)).toBe(false);
49
+ });
50
+ });
51
+ describe('registry', () => {
52
+ it('runs the handler of a shortcut and reports it', () => {
53
+ const registry = createShortcutRegistry({ platform: 'other' });
54
+ const undo = vi.fn();
55
+ registry.bind('edit.undo', undo);
56
+ expect(registry.handle(press('z', { ctrl: true }), { typing: false })).toBe(true);
57
+ expect(undo).toHaveBeenCalledOnce();
58
+ });
59
+ it('does nothing while typing', () => {
60
+ const registry = createShortcutRegistry({ platform: 'other' });
61
+ const undo = vi.fn();
62
+ registry.bind('edit.undo', undo);
63
+ expect(registry.handle(press('z', { ctrl: true }), { typing: true })).toBe(false);
64
+ expect(undo).not.toHaveBeenCalled();
65
+ });
66
+ it('leaves the key alone when the handler declines', () => {
67
+ const registry = createShortcutRegistry({ platform: 'other' });
68
+ registry.bind('edit.delete', () => false);
69
+ expect(registry.handle(press('Delete'), { typing: false })).toBe(false);
70
+ });
71
+ it('only fires bindings of an active scope, the latest first', () => {
72
+ const registry = createShortcutRegistry({ platform: 'other' });
73
+ const editor = vi.fn();
74
+ const dialog = vi.fn();
75
+ registry.bind('selection.clear', editor);
76
+ registry.bind('selection.clear', dialog, 'dialog');
77
+ registry.handle(press('Escape'), { typing: false });
78
+ expect(dialog).not.toHaveBeenCalled();
79
+ expect(editor).toHaveBeenCalledOnce();
80
+ registry.setScopes(['dialog']);
81
+ registry.handle(press('Escape'), { typing: false });
82
+ expect(dialog).toHaveBeenCalledOnce();
83
+ expect(editor).toHaveBeenCalledOnce();
84
+ });
85
+ it('applies overrides, and an empty override turns a shortcut off', () => {
86
+ const registry = createShortcutRegistry({
87
+ platform: 'other',
88
+ overrides: { 'edit.duplicate': 'mod+j', 'edit.copy': '' },
89
+ });
90
+ const duplicate = vi.fn();
91
+ registry.bind('edit.duplicate', duplicate);
92
+ expect(registry.handle(press('d', { ctrl: true }), { typing: false })).toBe(false);
93
+ expect(registry.handle(press('j', { ctrl: true }), { typing: false })).toBe(true);
94
+ expect(registry.keysFor('edit.copy')).toEqual([]);
95
+ });
96
+ it('gives every shortcut in the map its own combinations', () => {
97
+ const seen = new Set();
98
+ for (const shortcut of DEFAULT_SHORTCUTS) {
99
+ for (const combo of shortcut.keys) {
100
+ expect(seen.has(combo)).toBe(false);
101
+ seen.add(combo);
102
+ }
103
+ }
104
+ });
105
+ });
106
+ const item = {
107
+ type: 'buildr/item',
108
+ version: 1,
109
+ label: 'Item',
110
+ category: 'content',
111
+ props: {},
112
+ contentCategories: ['flow'],
113
+ styles: { groups: [] },
114
+ runtime: 'shared',
115
+ slots: { default: {} },
116
+ };
117
+ const page = {
118
+ ...item,
119
+ type: 'buildr/page',
120
+ label: 'Page',
121
+ capabilities: { root: true },
122
+ };
123
+ const registryMeta = createRegistryMeta({ components: [page, item] });
124
+ const fixture = () => ({
125
+ schemaVersion: 1,
126
+ root: 'root',
127
+ nodes: {
128
+ root: {
129
+ id: 'root',
130
+ type: 'buildr/page',
131
+ slots: { default: ['itemAAAAA1', 'itemBBBBB1', 'itemCCCCC1'] },
132
+ },
133
+ itemAAAAA1: { id: 'itemAAAAA1', type: 'buildr/item' },
134
+ itemBBBBB1: { id: 'itemBBBBB1', type: 'buildr/item' },
135
+ itemCCCCC1: { id: 'itemCCCCC1', type: 'buildr/item' },
136
+ },
137
+ components: {},
138
+ });
139
+ describe('ShortcutProvider', () => {
140
+ let container;
141
+ let root;
142
+ let forwarded;
143
+ const actions = {
144
+ copy: vi.fn(() => true),
145
+ cut: vi.fn(() => true),
146
+ paste: vi.fn(() => true),
147
+ save: vi.fn(() => true),
148
+ };
149
+ function Probe() {
150
+ forwarded = useForwardedKeys();
151
+ return _jsx("input", { "aria-label": "field" });
152
+ }
153
+ async function mount() {
154
+ const store = createEditorStore({
155
+ doc: fixture(),
156
+ registry: registryMeta,
157
+ generateId: createSeededIdGenerator(5),
158
+ validationDelayMs: null,
159
+ });
160
+ await act(async () => root.render(_jsx(MessagesProvider, { locale: "en", children: _jsx(EditorStoreProvider, { store: store, children: _jsx(ShortcutProvider, { platform: "other", actions: actions, children: _jsx(Probe, {}) }) }) })));
161
+ return store;
162
+ }
163
+ const key = (target, init) => act(async () => {
164
+ target.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, cancelable: true, ...init }));
165
+ });
166
+ const order = (store) => store.getState().doc.nodes['root']?.slots?.['default'];
167
+ beforeEach(() => {
168
+ container = document.createElement('div');
169
+ document.body.append(container);
170
+ root = createRoot(container);
171
+ for (const fn of Object.values(actions))
172
+ fn.mockClear();
173
+ });
174
+ afterEach(() => {
175
+ act(() => root.unmount());
176
+ document.body.innerHTML = '';
177
+ });
178
+ it('deletes, undoes and redoes the selection', async () => {
179
+ const store = await mount();
180
+ act(() => store.select('itemBBBBB1'));
181
+ await key(document.body, { key: 'Delete' });
182
+ expect(order(store)).toEqual(['itemAAAAA1', 'itemCCCCC1']);
183
+ await key(document.body, { key: 'z', ctrlKey: true });
184
+ expect(order(store)).toEqual(['itemAAAAA1', 'itemBBBBB1', 'itemCCCCC1']);
185
+ await key(document.body, { key: 'Z', ctrlKey: true, shiftKey: true });
186
+ expect(order(store)).toEqual(['itemAAAAA1', 'itemCCCCC1']);
187
+ });
188
+ it('duplicates, moves and clears', async () => {
189
+ const store = await mount();
190
+ act(() => store.select('itemBBBBB1'));
191
+ await key(document.body, { key: 'ArrowUp', altKey: true });
192
+ expect(order(store)).toEqual(['itemBBBBB1', 'itemAAAAA1', 'itemCCCCC1']);
193
+ await key(document.body, { key: 'ArrowDown', altKey: true });
194
+ expect(order(store)).toEqual(['itemAAAAA1', 'itemBBBBB1', 'itemCCCCC1']);
195
+ await key(document.body, { key: 'd', ctrlKey: true });
196
+ expect(order(store)?.length).toBe(4);
197
+ await key(document.body, { key: 'Escape' });
198
+ expect(store.getState().selectedIds).toEqual([]);
199
+ });
200
+ it('selects the siblings of the anchor', async () => {
201
+ const store = await mount();
202
+ act(() => store.select('itemAAAAA1'));
203
+ await key(document.body, { key: 'a', ctrlKey: true });
204
+ expect(store.getState().selectedIds).toEqual(['itemAAAAA1', 'itemBBBBB1', 'itemCCCCC1']);
205
+ });
206
+ it('calls the actions of other modules and prevents the browser default', async () => {
207
+ await mount();
208
+ const event = new KeyboardEvent('keydown', {
209
+ key: 's',
210
+ ctrlKey: true,
211
+ bubbles: true,
212
+ cancelable: true,
213
+ });
214
+ await act(async () => {
215
+ document.body.dispatchEvent(event);
216
+ });
217
+ expect(actions.save).toHaveBeenCalledOnce();
218
+ expect(event.defaultPrevented).toBe(true);
219
+ for (const [name, k] of [
220
+ ['copy', 'c'],
221
+ ['cut', 'x'],
222
+ ['paste', 'v'],
223
+ ]) {
224
+ await key(document.body, { key: k, ctrlKey: true });
225
+ expect(actions[name]).toHaveBeenCalledOnce();
226
+ }
227
+ });
228
+ it('does not fire while a text field has focus', async () => {
229
+ const store = await mount();
230
+ act(() => store.select('itemBBBBB1'));
231
+ const field = container.querySelector('input');
232
+ await key(field, { key: 'Delete' });
233
+ await key(field, { key: 'z', ctrlKey: true });
234
+ await key(field, { key: 's', ctrlKey: true });
235
+ expect(order(store)).toEqual(['itemAAAAA1', 'itemBBBBB1', 'itemCCCCC1']);
236
+ expect(actions.save).not.toHaveBeenCalled();
237
+ });
238
+ it('does not swallow a key it cannot act on', async () => {
239
+ await mount();
240
+ const event = new KeyboardEvent('keydown', { key: 'Delete', bubbles: true, cancelable: true });
241
+ await act(async () => {
242
+ document.body.dispatchEvent(event);
243
+ });
244
+ expect(event.defaultPrevented).toBe(false);
245
+ });
246
+ it('handles keys forwarded from the canvas', async () => {
247
+ const store = await mount();
248
+ act(() => store.select('itemAAAAA1'));
249
+ let handled = false;
250
+ await act(async () => {
251
+ handled = forwarded(press('Delete'));
252
+ });
253
+ expect(handled).toBe(true);
254
+ expect(order(store)).toEqual(['itemBBBBB1', 'itemCCCCC1']);
255
+ });
256
+ it('opens a help dialog listing the shortcuts with ?', async () => {
257
+ await mount();
258
+ await key(document.body, { key: '?', shiftKey: true });
259
+ const dialog = document.querySelector('[role=dialog]');
260
+ expect(dialog?.textContent).toContain('Keyboard shortcuts');
261
+ expect(dialog?.textContent).toContain('Ctrl+Shift+Z');
262
+ });
263
+ });