torch-glare 2.5.6 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (362) hide show
  1. package/README.md +4 -3
  2. package/dist/bin/index.js +9 -24
  3. package/dist/bin/index.js.map +1 -1
  4. package/dist/src/commands/add.d.ts +2 -2
  5. package/dist/src/commands/add.d.ts.map +1 -1
  6. package/dist/src/commands/add.js +4 -70
  7. package/dist/src/commands/add.js.map +1 -1
  8. package/dist/src/commands/hook.d.ts +5 -4
  9. package/dist/src/commands/hook.d.ts.map +1 -1
  10. package/dist/src/commands/hook.js +7 -75
  11. package/dist/src/commands/hook.js.map +1 -1
  12. package/dist/src/commands/init.js +1 -1
  13. package/dist/src/commands/init.js.map +1 -1
  14. package/dist/src/commands/layout.d.ts +5 -4
  15. package/dist/src/commands/layout.d.ts.map +1 -1
  16. package/dist/src/commands/layout.js +7 -75
  17. package/dist/src/commands/layout.js.map +1 -1
  18. package/dist/src/commands/provider.d.ts +5 -4
  19. package/dist/src/commands/provider.d.ts.map +1 -1
  20. package/dist/src/commands/provider.js +7 -75
  21. package/dist/src/commands/provider.js.map +1 -1
  22. package/dist/src/commands/update.d.ts.map +1 -1
  23. package/dist/src/commands/update.js +78 -43
  24. package/dist/src/commands/update.js.map +1 -1
  25. package/dist/src/commands/utils.d.ts +5 -4
  26. package/dist/src/commands/utils.d.ts.map +1 -1
  27. package/dist/src/commands/utils.js +7 -80
  28. package/dist/src/commands/utils.js.map +1 -1
  29. package/dist/src/shared/addFromRegistry.d.ts +16 -0
  30. package/dist/src/shared/addFromRegistry.d.ts.map +1 -0
  31. package/dist/src/shared/addFromRegistry.js +88 -0
  32. package/dist/src/shared/addFromRegistry.js.map +1 -0
  33. package/dist/src/shared/getInstallCommand.d.ts.map +1 -1
  34. package/dist/src/shared/getInstallCommand.js +5 -0
  35. package/dist/src/shared/getInstallCommand.js.map +1 -1
  36. package/dist/src/shared/installDependencies.d.ts +0 -10
  37. package/dist/src/shared/installDependencies.d.ts.map +1 -1
  38. package/dist/src/shared/installDependencies.js +0 -17
  39. package/dist/src/shared/installDependencies.js.map +1 -1
  40. package/dist/src/shared/installFromPlan.d.ts +7 -5
  41. package/dist/src/shared/installFromPlan.d.ts.map +1 -1
  42. package/dist/src/shared/installFromPlan.js +103 -36
  43. package/dist/src/shared/installFromPlan.js.map +1 -1
  44. package/dist/src/shared/loadRegistry.d.ts +12 -3
  45. package/dist/src/shared/loadRegistry.d.ts.map +1 -1
  46. package/dist/src/shared/loadRegistry.js +19 -20
  47. package/dist/src/shared/loadRegistry.js.map +1 -1
  48. package/dist/src/shared/registryClient.d.ts +19 -0
  49. package/dist/src/shared/registryClient.d.ts.map +1 -0
  50. package/dist/src/shared/registryClient.js +128 -0
  51. package/dist/src/shared/registryClient.js.map +1 -0
  52. package/dist/src/shared/resolveEntry.d.ts +10 -7
  53. package/dist/src/shared/resolveEntry.d.ts.map +1 -1
  54. package/dist/src/shared/resolveEntry.js +18 -13
  55. package/dist/src/shared/resolveEntry.js.map +1 -1
  56. package/dist/src/shared/suggestOtherCommand.d.ts +7 -1
  57. package/dist/src/shared/suggestOtherCommand.d.ts.map +1 -1
  58. package/dist/src/shared/suggestOtherCommand.js +29 -23
  59. package/dist/src/shared/suggestOtherCommand.js.map +1 -1
  60. package/dist/src/types/main.d.ts +31 -2
  61. package/dist/src/types/main.d.ts.map +1 -1
  62. package/package.json +6 -11
  63. package/apps/lib/components/ActionButton.tsx +0 -93
  64. package/apps/lib/components/ActionsGroup.tsx +0 -27
  65. package/apps/lib/components/AlertDialog.tsx +0 -204
  66. package/apps/lib/components/Avatar.tsx +0 -46
  67. package/apps/lib/components/Badge.tsx +0 -250
  68. package/apps/lib/components/BadgeField.tsx +0 -403
  69. package/apps/lib/components/Breadcrumb.tsx +0 -280
  70. package/apps/lib/components/Button.tsx +0 -325
  71. package/apps/lib/components/ButtonGroup.tsx +0 -190
  72. package/apps/lib/components/Calendar.tsx +0 -115
  73. package/apps/lib/components/Card.tsx +0 -95
  74. package/apps/lib/components/Checkbox.tsx +0 -42
  75. package/apps/lib/components/ColorPicker.tsx +0 -441
  76. package/apps/lib/components/ConclusionHeader.tsx +0 -148
  77. package/apps/lib/components/ContextMenu.tsx +0 -571
  78. package/apps/lib/components/CountBadge.tsx +0 -52
  79. package/apps/lib/components/DataTable.tsx +0 -213
  80. package/apps/lib/components/DataViews/badge.ts +0 -49
  81. package/apps/lib/components/DataViews/cell.tsx +0 -324
  82. package/apps/lib/components/DataViews/context.ts +0 -144
  83. package/apps/lib/components/DataViews/data-views.tsx +0 -395
  84. package/apps/lib/components/DataViews/filters/children.tsx +0 -98
  85. package/apps/lib/components/DataViews/filters/custom.tsx +0 -34
  86. package/apps/lib/components/DataViews/filters/filters.tsx +0 -157
  87. package/apps/lib/components/DataViews/filters/index.ts +0 -4
  88. package/apps/lib/components/DataViews/filters/labelled.tsx +0 -20
  89. package/apps/lib/components/DataViews/filters/presets.tsx +0 -65
  90. package/apps/lib/components/DataViews/filters/sync.tsx +0 -35
  91. package/apps/lib/components/DataViews/filters/values.ts +0 -173
  92. package/apps/lib/components/DataViews/header.tsx +0 -220
  93. package/apps/lib/components/DataViews/hooks/index.ts +0 -5
  94. package/apps/lib/components/DataViews/hooks/useActiveRow.ts +0 -22
  95. package/apps/lib/components/DataViews/hooks/useControllable.ts +0 -52
  96. package/apps/lib/components/DataViews/index.ts +0 -88
  97. package/apps/lib/components/DataViews/panel/columns.tsx +0 -153
  98. package/apps/lib/components/DataViews/panel/controls.tsx +0 -106
  99. package/apps/lib/components/DataViews/panel/index.ts +0 -3
  100. package/apps/lib/components/DataViews/panel/panel.tsx +0 -164
  101. package/apps/lib/components/DataViews/panel/saved-views.tsx +0 -67
  102. package/apps/lib/components/DataViews/panel/section.tsx +0 -81
  103. package/apps/lib/components/DataViews/panel/sort.tsx +0 -42
  104. package/apps/lib/components/DataViews/panel/tab.tsx +0 -31
  105. package/apps/lib/components/DataViews/slots.ts +0 -72
  106. package/apps/lib/components/DataViews/states.tsx +0 -73
  107. package/apps/lib/components/DataViews/types.ts +0 -510
  108. package/apps/lib/components/DataViews/views/board-view.tsx +0 -381
  109. package/apps/lib/components/DataViews/views/card-rows.tsx +0 -36
  110. package/apps/lib/components/DataViews/views/inbox-view.tsx +0 -260
  111. package/apps/lib/components/DataViews/views/pane-views.tsx +0 -196
  112. package/apps/lib/components/DataViews/views/table-view.tsx +0 -493
  113. package/apps/lib/components/DataViews/views/tree-view.tsx +0 -367
  114. package/apps/lib/components/DatePicker.tsx +0 -232
  115. package/apps/lib/components/Dialog.tsx +0 -116
  116. package/apps/lib/components/Divider.tsx +0 -28
  117. package/apps/lib/components/Drawer.tsx +0 -451
  118. package/apps/lib/components/DropdownMenu.tsx +0 -554
  119. package/apps/lib/components/FieldHint.tsx +0 -69
  120. package/apps/lib/components/Form.tsx +0 -182
  121. package/apps/lib/components/FormBuilder/context.ts +0 -85
  122. package/apps/lib/components/FormBuilder/field-kind.ts +0 -28
  123. package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +0 -60
  124. package/apps/lib/components/FormBuilder/fields/ColorField.tsx +0 -59
  125. package/apps/lib/components/FormBuilder/fields/CustomField.tsx +0 -11
  126. package/apps/lib/components/FormBuilder/fields/DateField.tsx +0 -32
  127. package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +0 -74
  128. package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +0 -168
  129. package/apps/lib/components/FormBuilder/fields/FileField.tsx +0 -39
  130. package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +0 -132
  131. package/apps/lib/components/FormBuilder/fields/OtpField.tsx +0 -31
  132. package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +0 -109
  133. package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +0 -31
  134. package/apps/lib/components/FormBuilder/fields/SelectField.tsx +0 -114
  135. package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +0 -157
  136. package/apps/lib/components/FormBuilder/fields/SliderField.tsx +0 -67
  137. package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +0 -41
  138. package/apps/lib/components/FormBuilder/fields/TableField.tsx +0 -336
  139. package/apps/lib/components/FormBuilder/fields/TextField.tsx +0 -213
  140. package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +0 -43
  141. package/apps/lib/components/FormBuilder/fields/countries.ts +0 -303
  142. package/apps/lib/components/FormBuilder/fields/index.ts +0 -25
  143. package/apps/lib/components/FormBuilder/form-builder.tsx +0 -198
  144. package/apps/lib/components/FormBuilder/index.ts +0 -31
  145. package/apps/lib/components/FormBuilder/numberFormat.ts +0 -16
  146. package/apps/lib/components/FormBuilder/submit.tsx +0 -67
  147. package/apps/lib/components/FormBuilder/types.ts +0 -316
  148. package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -250
  149. package/apps/lib/components/FormRenderer/detail.tsx +0 -256
  150. package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -358
  151. package/apps/lib/components/FormRenderer/header.tsx +0 -88
  152. package/apps/lib/components/FormRenderer/index.ts +0 -17
  153. package/apps/lib/components/FormRenderer/notch-action.tsx +0 -64
  154. package/apps/lib/components/FormRenderer/section.tsx +0 -39
  155. package/apps/lib/components/FormRenderer/stepper.tsx +0 -393
  156. package/apps/lib/components/FormRenderer/types.ts +0 -115
  157. package/apps/lib/components/FormSummary.tsx +0 -282
  158. package/apps/lib/components/HeaderBar.tsx +0 -117
  159. package/apps/lib/components/ImageAttachment.tsx +0 -209
  160. package/apps/lib/components/InnerLabelField.tsx +0 -154
  161. package/apps/lib/components/Input.tsx +0 -224
  162. package/apps/lib/components/InputField.tsx +0 -147
  163. package/apps/lib/components/InputOTP.tsx +0 -84
  164. package/apps/lib/components/Label.tsx +0 -129
  165. package/apps/lib/components/LabelField.tsx +0 -76
  166. package/apps/lib/components/LabeledCheckBox.tsx +0 -51
  167. package/apps/lib/components/LabeledRadio.tsx +0 -51
  168. package/apps/lib/components/LinkButton.tsx +0 -94
  169. package/apps/lib/components/LoginButton.tsx +0 -51
  170. package/apps/lib/components/PasswordLevel.tsx +0 -58
  171. package/apps/lib/components/Popover.tsx +0 -312
  172. package/apps/lib/components/ProfileMenu.tsx +0 -85
  173. package/apps/lib/components/Radio.tsx +0 -59
  174. package/apps/lib/components/RadioCard.tsx +0 -50
  175. package/apps/lib/components/ScrollArea.tsx +0 -54
  176. package/apps/lib/components/SearchField.tsx +0 -62
  177. package/apps/lib/components/SearchableSelect.tsx +0 -318
  178. package/apps/lib/components/SearchableTable.tsx +0 -344
  179. package/apps/lib/components/SearchableTree.tsx +0 -485
  180. package/apps/lib/components/SearchableTreeDialog.tsx +0 -502
  181. package/apps/lib/components/SectionBlock.tsx +0 -168
  182. package/apps/lib/components/Select.tsx +0 -347
  183. package/apps/lib/components/SimpleSelect.tsx +0 -225
  184. package/apps/lib/components/Skeleton.tsx +0 -12
  185. package/apps/lib/components/SlideDatePicker.tsx +0 -255
  186. package/apps/lib/components/SpinLoading.tsx +0 -174
  187. package/apps/lib/components/Stepper.tsx +0 -480
  188. package/apps/lib/components/Switch.tsx +0 -82
  189. package/apps/lib/components/TabFormItem.tsx +0 -153
  190. package/apps/lib/components/TabSwitch.tsx +0 -172
  191. package/apps/lib/components/Table.tsx +0 -597
  192. package/apps/lib/components/TextEditor/ChartBlockTool.ts +0 -676
  193. package/apps/lib/components/TextEditor/RichTextField.tsx +0 -46
  194. package/apps/lib/components/TextEditor/TableDnDWrapper.ts +0 -462
  195. package/apps/lib/components/TextEditor/TextEditor.tsx +0 -1164
  196. package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +0 -429
  197. package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +0 -70
  198. package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +0 -50
  199. package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +0 -48
  200. package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +0 -98
  201. package/apps/lib/components/TextEditor/editorjs.d.ts +0 -60
  202. package/apps/lib/components/TextEditor/index.ts +0 -7
  203. package/apps/lib/components/TextEditor/markdownParser.ts +0 -346
  204. package/apps/lib/components/Textarea.tsx +0 -117
  205. package/apps/lib/components/Timeline.tsx +0 -263
  206. package/apps/lib/components/Toast.tsx +0 -87
  207. package/apps/lib/components/Toggle.tsx +0 -125
  208. package/apps/lib/components/ToggleButton.tsx +0 -140
  209. package/apps/lib/components/Tooltip.tsx +0 -116
  210. package/apps/lib/components/TransparentLabel.tsx +0 -71
  211. package/apps/lib/components/TreeDropDown.tsx +0 -115
  212. package/apps/lib/components/TreeFolder/TreeFolder.tsx +0 -380
  213. package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +0 -75
  214. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +0 -354
  215. package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +0 -60
  216. package/apps/lib/components/TreeFolder/icons.tsx +0 -60
  217. package/apps/lib/components/TreeFolder/index.ts +0 -24
  218. package/apps/lib/components/TreeFolder/treeFolderUtils.ts +0 -109
  219. package/apps/lib/components/TreeFolder/types.ts +0 -77
  220. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +0 -118
  221. package/apps/lib/hooks/useActiveTreeItem.ts +0 -61
  222. package/apps/lib/hooks/useClickOutside.ts +0 -27
  223. package/apps/lib/hooks/useDragDrop.tsx +0 -365
  224. package/apps/lib/hooks/useHtmlDir.ts +0 -31
  225. package/apps/lib/hooks/useInfiniteScroll.ts +0 -108
  226. package/apps/lib/hooks/useIsMobile.ts +0 -21
  227. package/apps/lib/hooks/useResize.ts +0 -67
  228. package/apps/lib/hooks/useTagSelection.ts +0 -300
  229. package/apps/lib/layouts/CNLayout.tsx +0 -372
  230. package/apps/lib/layouts/DataViewCard.tsx +0 -62
  231. package/apps/lib/layouts/FieldSection.tsx +0 -91
  232. package/apps/lib/layouts/TreeSubLayout.tsx +0 -173
  233. package/apps/lib/providers/ThemeProvider.tsx +0 -84
  234. package/apps/lib/registry.json +0 -1217
  235. package/apps/lib/tsconfig.json +0 -9
  236. package/apps/lib/tsconfig.tsbuildinfo +0 -1
  237. package/apps/lib/utils/cn.ts +0 -6
  238. package/apps/lib/utils/color.ts +0 -175
  239. package/apps/lib/utils/dataViews/path.ts +0 -67
  240. package/apps/lib/utils/dataViews/query.ts +0 -73
  241. package/apps/lib/utils/dataViews/types.ts +0 -187
  242. package/apps/lib/utils/dateFormat.ts +0 -108
  243. package/apps/lib/utils/resize.ts +0 -31
  244. package/apps/lib/utils/scroller.ts +0 -26
  245. package/apps/lib/utils/types.ts +0 -16
  246. package/docs/BLOCKS.md +0 -129
  247. package/docs/CHANGELOG-1.1.16.md +0 -108
  248. package/docs/Cover.png +0 -0
  249. package/docs/README.md +0 -215
  250. package/docs/components/action-button.md +0 -638
  251. package/docs/components/actions-group.md +0 -708
  252. package/docs/components/alert-dialog.md +0 -920
  253. package/docs/components/avatar.md +0 -709
  254. package/docs/components/badge-field.md +0 -738
  255. package/docs/components/badge.md +0 -301
  256. package/docs/components/breadcrumb.md +0 -930
  257. package/docs/components/button-group.md +0 -650
  258. package/docs/components/button.md +0 -639
  259. package/docs/components/calendar.md +0 -555
  260. package/docs/components/card.md +0 -622
  261. package/docs/components/chart-block-tool.md +0 -129
  262. package/docs/components/checkbox.md +0 -699
  263. package/docs/components/cn-layout.md +0 -854
  264. package/docs/components/color-picker.md +0 -101
  265. package/docs/components/conclusion-header.md +0 -80
  266. package/docs/components/context-menu.md +0 -483
  267. package/docs/components/count-badge.md +0 -560
  268. package/docs/components/data-table.md +0 -854
  269. package/docs/components/data-views/backend-response.md +0 -324
  270. package/docs/components/data-views/examples/a11y-rtl.md +0 -250
  271. package/docs/components/data-views/examples/api-orders-route.md +0 -130
  272. package/docs/components/data-views/examples/fields.md +0 -362
  273. package/docs/components/data-views/examples/filters.md +0 -307
  274. package/docs/components/data-views/examples/inbox-routing.md +0 -218
  275. package/docs/components/data-views/examples/index.md +0 -29
  276. package/docs/components/data-views/examples/overview.md +0 -244
  277. package/docs/components/data-views/examples/panel.md +0 -212
  278. package/docs/components/data-views/examples/scale.md +0 -231
  279. package/docs/components/data-views/examples/server-side.md +0 -210
  280. package/docs/components/data-views/examples/state.md +0 -250
  281. package/docs/components/data-views/examples/tree-custom.md +0 -388
  282. package/docs/components/data-views/examples/view-registry.md +0 -313
  283. package/docs/components/data-views/examples/views.md +0 -534
  284. package/docs/components/data-views/guide.md +0 -405
  285. package/docs/components/data-views/index.md +0 -1521
  286. package/docs/components/data-views/migration.md +0 -81
  287. package/docs/components/date-picker.md +0 -857
  288. package/docs/components/dialog.md +0 -929
  289. package/docs/components/divider.md +0 -766
  290. package/docs/components/drawer.md +0 -654
  291. package/docs/components/dropdown-menu.md +0 -668
  292. package/docs/components/field-hint.md +0 -898
  293. package/docs/components/field-section.md +0 -781
  294. package/docs/components/form-builder.md +0 -284
  295. package/docs/components/form-renderer.md +0 -396
  296. package/docs/components/form-summary.md +0 -138
  297. package/docs/components/form.md +0 -785
  298. package/docs/components/header-bar.md +0 -188
  299. package/docs/components/image-attachment.md +0 -906
  300. package/docs/components/inner-label-field.md +0 -819
  301. package/docs/components/input-field.md +0 -623
  302. package/docs/components/input-otp.md +0 -756
  303. package/docs/components/input.md +0 -634
  304. package/docs/components/label-field.md +0 -770
  305. package/docs/components/label.md +0 -761
  306. package/docs/components/labeled-check-box.md +0 -642
  307. package/docs/components/labeled-radio.md +0 -796
  308. package/docs/components/link-button.md +0 -685
  309. package/docs/components/login-button.md +0 -872
  310. package/docs/components/password-level.md +0 -803
  311. package/docs/components/popover.md +0 -649
  312. package/docs/components/profile-menu.md +0 -656
  313. package/docs/components/radio-card.md +0 -801
  314. package/docs/components/radio.md +0 -735
  315. package/docs/components/scroll-area.md +0 -691
  316. package/docs/components/search-field.md +0 -702
  317. package/docs/components/searchable-select.md +0 -368
  318. package/docs/components/searchable-table.md +0 -438
  319. package/docs/components/searchable-tree-dialog.md +0 -190
  320. package/docs/components/searchable-tree.md +0 -200
  321. package/docs/components/section-block.md +0 -483
  322. package/docs/components/select.md +0 -709
  323. package/docs/components/simple-select.md +0 -741
  324. package/docs/components/skeleton.md +0 -706
  325. package/docs/components/slide-date-picker.md +0 -837
  326. package/docs/components/spin-loading.md +0 -696
  327. package/docs/components/stepper.md +0 -316
  328. package/docs/components/switch.md +0 -770
  329. package/docs/components/tab-form-item.md +0 -773
  330. package/docs/components/tab-switch.md +0 -170
  331. package/docs/components/table-dnd-wrapper.md +0 -107
  332. package/docs/components/table.md +0 -1088
  333. package/docs/components/text-editor.md +0 -735
  334. package/docs/components/textarea.md +0 -681
  335. package/docs/components/timeline.md +0 -254
  336. package/docs/components/toast.md +0 -773
  337. package/docs/components/toggle-button.md +0 -643
  338. package/docs/components/toggle.md +0 -882
  339. package/docs/components/tooltip.md +0 -513
  340. package/docs/components/transparent-label.md +0 -721
  341. package/docs/components/tree-drop-down.md +0 -740
  342. package/docs/components/tree-folder.md +0 -110
  343. package/docs/components/tree-sub-layout.md +0 -707
  344. package/docs/explanation/architecture.md +0 -54
  345. package/docs/explanation/design-system.md +0 -52
  346. package/docs/how-to/form-and-list-recipes.md +0 -386
  347. package/docs/how-to/forms-with-form-builder.md +0 -472
  348. package/docs/how-to/guides.md +0 -1027
  349. package/docs/migration/changelog.md +0 -60
  350. package/docs/migration/form-builder-2.5.2.md +0 -113
  351. package/docs/reference/cli.md +0 -112
  352. package/docs/reference/components.md +0 -572
  353. package/docs/reference/hooks.md +0 -1523
  354. package/docs/reference/providers.md +0 -866
  355. package/docs/reference/tailwind-plugins.md +0 -942
  356. package/docs/reference/theme.md +0 -85
  357. package/docs/reference/types.md +0 -1016
  358. package/docs/reference/utilities.md +0 -726
  359. package/docs/tutorials/building-first-form.md +0 -846
  360. package/docs/tutorials/component-composition.md +0 -882
  361. package/docs/tutorials/getting-started.md +0 -302
  362. package/docs/tutorials/theming-basics.md +0 -785
@@ -1,735 +0,0 @@
1
- ---
2
- name: TextEditor
3
- version: 2.4.5
4
- status: stable
5
- category: components/editors
6
- tags: [editor, rich-text, block-editor, editorjs, markdown, rtl, accessible]
7
- last-reviewed: 2024-11-05
8
- bundle-size: 45kb
9
- dependencies:
10
- - "@editorjs/editorjs": "^2.28.0"
11
- - "@editorjs/header": "^2.8.0"
12
- - "@editorjs/list": "^1.9.0"
13
- - "@editorjs/nested-list": "^1.4.0"
14
- - "@editorjs/checklist": "^1.6.0"
15
- - "@editorjs/quote": "^2.6.0"
16
- - "@editorjs/warning": "^1.4.0"
17
- - "@editorjs/code": "^2.9.0"
18
- - "@editorjs/delimiter": "^1.4.0"
19
- - "@editorjs/embed": "^2.7.0"
20
- - "@editorjs/table": "^2.3.0"
21
- - "@editorjs/link": "^2.6.0"
22
- - "@editorjs/simple-image": "^1.6.0"
23
- - "@editorjs/raw": "^2.5.0"
24
- - "@editorjs/marker": "^1.4.0"
25
- - "@editorjs/inline-code": "^1.5.0"
26
- - "@editorjs/underline": "^1.1.0"
27
- - "@editorjs/text-variant-tune": "^1.0.0"
28
- - "class-variance-authority": "^0.7.0"
29
- ---
30
-
31
- # TextEditor
32
-
33
- > A feature-rich block-style text editor built on Editor.js with 18+ block tools, automatic RTL/LTR detection, markdown paste support, dark mode theming, and imperative ref methods for programmatic control.
34
-
35
- ## Installation
36
-
37
- TORCH Glare is a copy-in library: the CLI copies this component's source into your project
38
- (you do **not** install it from the npm package). Run `init` once, then `add`:
39
-
40
- ```bash
41
- npx torch-glare@latest init
42
- npx torch-glare@latest add TextEditor
43
- ```
44
-
45
- `add` also copies any components, hooks, and utilities that `TextEditor` depends on.
46
-
47
- ## Import
48
-
49
- Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
50
-
51
- ```tsx
52
- import { TextEditor } from "@/components/TextEditor";
53
- ```
54
-
55
- ## Quick Examples
56
-
57
- ### Basic Usage
58
-
59
- ```typescript
60
- import { TextEditor } from "@/components/TextEditor";
61
-
62
- function Example() {
63
- return (
64
- <TextEditor
65
- placeholder="Start writing..."
66
- onChange={(data) => console.log(data)}
67
- />
68
- )
69
- }
70
- ```
71
-
72
- ### With Initial Data
73
-
74
- ```typescript
75
- import { TextEditor } from "@/components/TextEditor";
76
- import type { OutputData } from '@editorjs/editorjs'
77
-
78
- function Example() {
79
- const initialData: OutputData = {
80
- time: Date.now(),
81
- blocks: [
82
- {
83
- type: 'header',
84
- data: { text: 'Welcome', level: 2 }
85
- },
86
- {
87
- type: 'paragraph',
88
- data: { text: 'Start editing this document.' }
89
- }
90
- ]
91
- }
92
-
93
- return (
94
- <TextEditor
95
- data={initialData}
96
- onChange={(data) => console.log('Saved:', data)}
97
- />
98
- )
99
- }
100
- ```
101
-
102
- ### Controlled with Ref
103
-
104
- ```typescript
105
- import { useRef } from 'react'
106
- import { TextEditor, TextEditorRef } from "@/components/TextEditor";
107
-
108
- function EditorWithControls() {
109
- const editorRef = useRef<TextEditorRef>(null)
110
-
111
- const handleSave = async () => {
112
- if (editorRef.current) {
113
- const data = await editorRef.current.save()
114
- console.log('Editor content:', data)
115
- }
116
- }
117
-
118
- const handleClear = () => {
119
- editorRef.current?.clear()
120
- }
121
-
122
- return (
123
- <div>
124
- <div className="flex gap-2 mb-4">
125
- <button onClick={handleSave}>Save</button>
126
- <button onClick={handleClear}>Clear</button>
127
- </div>
128
- <TextEditor ref={editorRef} size="L" />
129
- </div>
130
- )
131
- }
132
- ```
133
-
134
- ### Different Sizes
135
-
136
- ```typescript
137
- <TextEditor size="S" placeholder="Small editor (200px)" />
138
- <TextEditor size="M" placeholder="Medium editor (300px)" />
139
- <TextEditor size="L" placeholder="Large editor (400px)" />
140
- <TextEditor size="XL" placeholder="Extra large editor (500px)" />
141
- ```
142
-
143
- ### Custom Min Height
144
-
145
- ```typescript
146
- <TextEditor
147
- minHeight={600}
148
- placeholder="Custom height editor"
149
- />
150
- ```
151
-
152
- ### Read-Only Mode
153
-
154
- ```typescript
155
- function ReadOnlyEditor({ content }: { content: OutputData }) {
156
- return (
157
- <TextEditor
158
- data={content}
159
- readOnly={true}
160
- size="L"
161
- />
162
- )
163
- }
164
- ```
165
-
166
- ### With Theme Override
167
-
168
- ```typescript
169
- <TextEditor theme="dark" size="M" placeholder="Dark theme editor" />
170
- <TextEditor theme="light" size="M" placeholder="Light theme editor" />
171
- ```
172
-
173
- ### Disabled State
174
-
175
- ```typescript
176
- <TextEditor
177
- disabled
178
- data={someData}
179
- size="M"
180
- />
181
- ```
182
-
183
- ### Custom Tools Override
184
-
185
- ```typescript
186
- import Header from '@editorjs/header'
187
- import List from '@editorjs/list'
188
-
189
- function MinimalEditor() {
190
- const customTools = {
191
- header: {
192
- class: Header,
193
- inlineToolbar: true,
194
- config: { levels: [2, 3], defaultLevel: 2 }
195
- },
196
- list: {
197
- class: List,
198
- inlineToolbar: true
199
- }
200
- }
201
-
202
- return (
203
- <TextEditor
204
- tools={customTools}
205
- placeholder="Only headers and lists allowed"
206
- />
207
- )
208
- }
209
- ```
210
-
211
- ### With onReady Callback
212
-
213
- ```typescript
214
- function EditorWithReadyState() {
215
- const [isReady, setIsReady] = useState(false)
216
-
217
- return (
218
- <div>
219
- {!isReady && <div>Loading editor...</div>}
220
- <TextEditor
221
- onReady={() => setIsReady(true)}
222
- placeholder="Editor loads asynchronously"
223
- />
224
- </div>
225
- )
226
- }
227
- ```
228
-
229
- ### Markdown Paste Support
230
-
231
- ```typescript
232
- function MarkdownEditor() {
233
- return (
234
- <TextEditor
235
- size="L"
236
- placeholder="Try pasting markdown content here..."
237
- onChange={(data) => console.log(data)}
238
- />
239
- )
240
- }
241
- // Pasting markdown like "# Heading\n- item 1\n- item 2" will
242
- // auto-convert to Editor.js header and list blocks.
243
- ```
244
-
245
- ## API Reference
246
-
247
- ### Props
248
-
249
- | Prop | Type | Default | Description |
250
- |------|------|---------|-------------|
251
- | `variant` | `'PresentationStyle'` | `'PresentationStyle'` | Visual style variant |
252
- | `size` | `'S' \| 'M' \| 'L' \| 'XL'` | - | Size preset controlling min-height and padding |
253
- | `theme` | `'light' \| 'dark' \| 'default'` | - | Override theme for this component |
254
- | `data` | `OutputData` | - | Initial editor content (Editor.js OutputData format) |
255
- | `onChange` | `(data: OutputData) => void` | - | Called when content changes (debounced) |
256
- | `onReady` | `() => void` | - | Called when editor finishes initialization |
257
- | `readOnly` | `boolean` | `false` | Makes the editor non-editable |
258
- | `placeholder` | `string` | `'Write something or press / to select a tool'` | Placeholder text for empty editor |
259
- | `autofocus` | `boolean` | `false` | Auto-focus the editor on mount |
260
- | `tools` | `Record<string, any>` | Default 18+ tools | Override the Editor.js tools configuration |
261
- | `minHeight` | `number` | - | Custom min-height in pixels (overrides size) |
262
- | `disabled` | `boolean` | `false` | Disables interaction with reduced opacity |
263
- | `toolbar` | `boolean` | `true` | Show the fixed formatting toolbar. Auto-hidden when `readOnly`/`disabled`. |
264
- | `className` | `string` | - | Additional CSS classes |
265
-
266
- ### Formatting toolbar
267
-
268
- A fixed, sticky toolbar sits at the top of the editor (shown by default; pass `toolbar={false}`
269
- to hide it, and it is automatically hidden in `readOnly`/`disabled` editors). It drives the
270
- underlying Editor.js instance and offers:
271
-
272
- - **History** — undo / redo (via `editorjs-undo`; also bound to `Ctrl/⌘+Z` / `Ctrl/⌘+Y`).
273
- - **Block type** — a dropdown to switch between Normal text and Heading 1–3 (`blocks.convert`).
274
- - **Alignment** — left / center / right (a block tune persisted on each block).
275
- - **Text color** — a swatch palette.
276
- - **Inline** — bold, italic, underline, strikethrough, clear formatting.
277
- - **Lists** — bullet and ordered.
278
- - **Insert image** — from a local file (inserted as an `image` block).
279
-
280
- Strikethrough and color are backed by small custom inline tools whose `sanitize` allowlists let
281
- that markup survive `save()`; alignment persists as a block tune.
282
-
283
- ### Ref Methods (TextEditorRef)
284
-
285
- | Method | Signature | Description |
286
- |--------|-----------|-------------|
287
- | `save` | `() => Promise<OutputData>` | Saves and returns the current editor content |
288
- | `clear` | `() => void` | Clears all editor content |
289
- | `render` | `(data: OutputData) => Promise<void>` | Renders the provided data into the editor |
290
- | `focus` | `(atEnd?: boolean) => boolean` | Focuses the editor; optionally at the end of content |
291
- | `getInstance` | `() => EditorJS \| null` | Returns the raw Editor.js instance |
292
-
293
- ### Size Variants
294
-
295
- | Size | Min Height | Padding |
296
- |------|-----------|---------|
297
- | S | 200px | 8px (p-2) |
298
- | M | 300px | 12px (p-3) |
299
- | L | 400px | 16px (p-4) |
300
- | XL | 500px | 20px (p-5) |
301
-
302
- ### Default Block Tools
303
-
304
- | Tool | Shortcut | Description |
305
- |------|----------|-------------|
306
- | Header | `Cmd+Shift+H` | H1-H6 headings |
307
- | List | `Cmd+Shift+L` | Ordered/unordered lists |
308
- | NestedList | - | Multi-level nested lists |
309
- | Checklist | - | Interactive checkboxes |
310
- | Quote | `Cmd+Shift+O` | Block quotes with caption |
311
- | Warning | - | Warning/notice blocks |
312
- | Code | `Cmd+Shift+C` | Code snippets |
313
- | Delimiter | - | Horizontal divider |
314
- | Embed | - | YouTube, Vimeo, CodePen, Twitter, Instagram, GitHub |
315
- | Table | `Cmd+Alt+T` | Data tables (default 2x3) |
316
- | LinkTool | - | Link previews |
317
- | SimpleImage | - | Image blocks via URL |
318
- | Raw | - | Raw HTML blocks |
319
- | Chart | - | Interactive chart blocks (bar, line, pie, doughnut, radar, polar) |
320
- | Marker | `Cmd+Shift+M` | Inline text highlighting |
321
- | InlineCode | `Cmd+Shift+I` | Inline code formatting |
322
- | Underline | - | Inline underline formatting |
323
- | TextVariant | - | Block-level text tune (callout, citation, details) |
324
-
325
- ### TypeScript
326
-
327
- ```typescript
328
- import { HTMLAttributes } from 'react'
329
- import { VariantProps } from 'class-variance-authority'
330
- import { OutputData } from '@editorjs/editorjs'
331
-
332
- type Themes = 'light' | 'dark' | 'default'
333
-
334
- export interface TextEditorRef {
335
- save: () => Promise<OutputData>
336
- clear: () => void
337
- render: (data: OutputData) => Promise<void>
338
- focus: (atEnd?: boolean) => boolean
339
- getInstance: () => EditorJS | null
340
- }
341
-
342
- interface TextEditorProps
343
- extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'>,
344
- VariantProps<typeof textEditorStyles> {
345
- theme?: Themes
346
- data?: OutputData
347
- onChange?: (data: OutputData) => void
348
- onReady?: () => void
349
- readOnly?: boolean
350
- placeholder?: string
351
- autofocus?: boolean
352
- tools?: Record<string, any>
353
- minHeight?: number
354
- }
355
-
356
- export const TextEditor: React.ForwardRefExoticComponent<
357
- TextEditorProps & React.RefAttributes<TextEditorRef>
358
- >
359
-
360
- export type { TextEditorProps, OutputData }
361
- ```
362
-
363
- ## Common Patterns
364
-
365
- ### Blog Post Editor
366
-
367
- ```typescript
368
- import { useRef, useState } from 'react'
369
- import { TextEditor, TextEditorRef } from "@/components/TextEditor";
370
- import { Button } from "@/components/Button";
371
- import type { OutputData } from '@editorjs/editorjs'
372
-
373
- function BlogPostEditor() {
374
- const editorRef = useRef<TextEditorRef>(null)
375
- const [isSaving, setIsSaving] = useState(false)
376
-
377
- const handlePublish = async () => {
378
- if (!editorRef.current) return
379
- setIsSaving(true)
380
-
381
- try {
382
- const content = await editorRef.current.save()
383
- await publishPost(content)
384
- } finally {
385
- setIsSaving(false)
386
- }
387
- }
388
-
389
- return (
390
- <div className="max-w-3xl mx-auto">
391
- <TextEditor
392
- ref={editorRef}
393
- size="XL"
394
- autofocus
395
- placeholder="Write your blog post..."
396
- onChange={(data) => autoSaveDraft(data)}
397
- />
398
- <div className="mt-4 flex justify-end">
399
- <Button
400
- variant="PrimeStyle"
401
- is_loading={isSaving}
402
- onClick={handlePublish}
403
- >
404
- Publish
405
- </Button>
406
- </div>
407
- </div>
408
- )
409
- }
410
- ```
411
-
412
- ### Preview Mode Toggle
413
-
414
- ```typescript
415
- function EditorWithPreview() {
416
- const editorRef = useRef<TextEditorRef>(null)
417
- const [readOnly, setReadOnly] = useState(false)
418
-
419
- return (
420
- <div>
421
- <div className="flex gap-2 mb-4">
422
- <Button
423
- variant={readOnly ? 'BorderStyle' : 'PrimeStyle'}
424
- onClick={() => setReadOnly(false)}
425
- >
426
- Edit
427
- </Button>
428
- <Button
429
- variant={readOnly ? 'PrimeStyle' : 'BorderStyle'}
430
- onClick={() => setReadOnly(true)}
431
- >
432
- Preview
433
- </Button>
434
- </div>
435
- <TextEditor
436
- ref={editorRef}
437
- readOnly={readOnly}
438
- size="L"
439
- />
440
- </div>
441
- )
442
- }
443
- ```
444
-
445
- ### Load and Render Saved Content
446
-
447
- ```typescript
448
- function DocumentViewer({ documentId }: { documentId: string }) {
449
- const editorRef = useRef<TextEditorRef>(null)
450
-
451
- useEffect(() => {
452
- async function loadDocument() {
453
- const data = await fetchDocument(documentId)
454
- await editorRef.current?.render(data)
455
- }
456
- loadDocument()
457
- }, [documentId])
458
-
459
- return (
460
- <TextEditor
461
- ref={editorRef}
462
- readOnly
463
- size="XL"
464
- />
465
- )
466
- }
467
- ```
468
-
469
- ### Form Integration
470
-
471
- ```typescript
472
- import { useForm, Controller } from 'react-hook-form'
473
-
474
- function ArticleForm() {
475
- const { control, handleSubmit } = useForm()
476
-
477
- return (
478
- <form onSubmit={handleSubmit(onSubmit)}>
479
- <Controller
480
- name="content"
481
- control={control}
482
- render={({ field }) => (
483
- <TextEditor
484
- data={field.value}
485
- onChange={field.onChange}
486
- size="L"
487
- placeholder="Article content..."
488
- />
489
- )}
490
- />
491
- <Button type="submit" variant="PrimeStyle">
492
- Save Article
493
- </Button>
494
- </form>
495
- )
496
- }
497
- ```
498
-
499
- ## Testing
500
-
501
- ### Unit Test Example
502
-
503
- ```typescript
504
- import { render, screen, waitFor } from '@testing-library/react'
505
- import { TextEditor, TextEditorRef } from "@/components/TextEditor";
506
-
507
- describe('TextEditor', () => {
508
- it('renders the editor container', () => {
509
- const { container } = render(
510
- <TextEditor size="M" />
511
- )
512
-
513
- expect(container.querySelector('.torch-text-editor')).toBeInTheDocument()
514
- })
515
-
516
- it('applies size class', () => {
517
- const { container } = render(
518
- <TextEditor size="L" />
519
- )
520
-
521
- const editor = container.querySelector('.torch-text-editor')
522
- expect(editor).toHaveClass('min-h-[400px]')
523
- })
524
-
525
- it('applies disabled state', () => {
526
- const { container } = render(
527
- <TextEditor disabled />
528
- )
529
-
530
- const editor = container.querySelector('.torch-text-editor')
531
- expect(editor).toHaveClass('cursor-not-allowed', 'pointer-events-none')
532
- })
533
-
534
- it('calls onReady when editor initializes', async () => {
535
- const onReady = jest.fn()
536
- render(<TextEditor onReady={onReady} />)
537
-
538
- await waitFor(() => {
539
- expect(onReady).toHaveBeenCalledTimes(1)
540
- })
541
- })
542
-
543
- it('exposes ref methods', async () => {
544
- const ref = React.createRef<TextEditorRef>()
545
- render(<TextEditor ref={ref} />)
546
-
547
- await waitFor(() => {
548
- expect(ref.current).toBeDefined()
549
- expect(ref.current?.save).toBeDefined()
550
- expect(ref.current?.clear).toBeDefined()
551
- expect(ref.current?.render).toBeDefined()
552
- expect(ref.current?.focus).toBeDefined()
553
- expect(ref.current?.getInstance).toBeDefined()
554
- })
555
- })
556
- })
557
- ```
558
-
559
- ## Accessibility
560
-
561
- ### Keyboard Support
562
-
563
- - **Tab**: Navigate between block tools and editor content
564
- - **Enter**: Create new block
565
- - **/**: Open block tool selector (slash command)
566
- - **Cmd+Shift+H**: Insert header
567
- - **Cmd+Shift+L**: Insert list
568
- - **Cmd+Shift+O**: Insert quote
569
- - **Cmd+Shift+C**: Insert code block
570
- - **Cmd+Alt+T**: Insert table
571
- - **Cmd+Shift+M**: Apply marker highlight
572
- - **Cmd+Shift+I**: Apply inline code
573
-
574
- ### ARIA Attributes
575
-
576
- The TextEditor renders semantic HTML through Editor.js:
577
-
578
- ```html
579
- <div
580
- data-theme="dark"
581
- class="torch-text-editor"
582
- spellcheck="false"
583
- translate="no"
584
- >
585
- <div id="torch-editor-xxxxx">
586
- <!-- Editor.js renders accessible content blocks -->
587
- </div>
588
- </div>
589
- ```
590
-
591
- ### RTL/LTR Support
592
-
593
- - Automatic per-block direction detection based on first visible character
594
- - Supports Arabic, Hebrew, Farsi, and other RTL scripts
595
- - List bullets and checkboxes flip correctly in RTL mode
596
- - Mixed-direction documents supported (each block detects independently)
597
-
598
- ### Screen Reader Support
599
-
600
- - Editor.js blocks render as semantic HTML (headings, lists, paragraphs)
601
- - Block tools accessible via keyboard navigation
602
- - Inline toolbar supports keyboard shortcuts
603
-
604
- ## Styling
605
-
606
- ### Custom Styles with className
607
-
608
- ```typescript
609
- <TextEditor
610
- className="shadow-lg border border-gray-200 rounded-lg"
611
- size="L"
612
- />
613
- ```
614
-
615
- ### Theme Customization
616
-
617
- ```css
618
- /* Custom theme variables */
619
- [data-theme="custom"] .torch-text-editor {
620
- --color-background: #your-bg;
621
- --color-text-primary: #your-text;
622
- --color-border: #your-border;
623
- }
624
- ```
625
-
626
- ### Dark Mode
627
-
628
- The TextEditor includes comprehensive dark mode CSS variable overrides for:
629
-
630
- - Editor.js core popover menus
631
- - Inline toolbar
632
- - Table plugin cells, borders, and toolbox
633
- - Search fields in popovers
634
- - Chart block tool elements
635
- - Scrollbar styling
636
-
637
- Dark mode activates automatically via `data-theme="dark"` on the component or a parent element.
638
-
639
- ### Design Token Classes
640
-
641
- The PresentationStyle variant maps to the following design tokens:
642
-
643
- - Background: `bg-background-presentation-form-field-primary`
644
- - Text: `text-content-presentation-global-primary`
645
- - Selection: `bg-background-presentation-action-hover`
646
- - Marker: `bg-background-presentation-state-warning-primary`
647
- - Toolbar: `text-content-presentation-action-light-primary`
648
- - Popover: `bg-background-presentation-form-field-primary`
649
- - Code: `bg-background-presentation-action-secondary`
650
-
651
- ## Performance
652
-
653
- | Metric | Value |
654
- |--------|-------|
655
- | Bundle size (gzip) | ~45kb (with all tools) |
656
- | First render | ~50ms |
657
- | onChange debounce | 500ms + requestIdleCallback |
658
- | Tree-shakeable | Partially (tools are bundled) |
659
-
660
- ### Optimization Tips
661
-
662
- 1. Use `tools` prop to include only needed block tools for smaller bundles
663
- 2. The `onChange` callback is debounced (500ms) and deferred to idle time via `requestIdleCallback`
664
- 3. Auto-direction uses `requestAnimationFrame` batching to avoid layout thrashing
665
- 4. Markdown paste uses a single `render()` call instead of per-block insertion
666
- 5. MutationObserver watches only direct children of the redactor (not full subtree)
667
-
668
- ## Troubleshooting
669
-
670
- ### Common Issues
671
-
672
- #### Editor not initializing
673
-
674
- **Solution:** Ensure the component is mounted in a client component with `"use client"` directive. TextEditor requires browser APIs.
675
-
676
- ```typescript
677
- "use client"
678
-
679
- import { TextEditor } from "@/components/TextEditor";
680
-
681
- export default function Page() {
682
- return <TextEditor />
683
- }
684
- ```
685
-
686
- #### onChange fires too frequently
687
-
688
- **Solution:** The onChange is already debounced at 500ms + `requestIdleCallback`. For additional throttling, wrap your handler:
689
-
690
- ```typescript
691
- const debouncedSave = useMemo(
692
- () => debounce((data: OutputData) => saveToServer(data), 2000),
693
- []
694
- )
695
-
696
- <TextEditor onChange={debouncedSave} />
697
- ```
698
-
699
- #### RTL text not detected
700
-
701
- **Solution:** The auto-direction detects RTL based on the first visible character. If your text starts with LTR characters (numbers, punctuation), the block will be LTR. Start with an RTL character for correct detection.
702
-
703
- #### Tailwind resets strip heading styles
704
-
705
- **Solution:** The TextEditor injects heading styles automatically via an internal stylesheet that restores h1-h6 sizing within the `.torch-text-editor` container. No additional configuration needed.
706
-
707
- ## Related Components
708
-
709
- - [Input](/docs/components/input.md) - Single-line text input
710
- - [Textarea](/docs/components/textarea.md) - Multi-line plain text input
711
- - [Form](/docs/components/form.md) - Form wrapper for validation
712
-
713
- ## Browser Support
714
-
715
- - Chrome 90+ (requestIdleCallback supported)
716
- - Firefox 88+ (requestIdleCallback supported)
717
- - Safari 14+ (fallback to setTimeout for requestIdleCallback)
718
- - Edge 90+
719
- - Mobile browsers (touch-friendly block controls)
720
-
721
- ## Changelog
722
-
723
- ### v1.1.15
724
- - Added ChartBlockTool for interactive chart creation
725
- - Added markdown paste support with auto-conversion
726
- - Added auto RTL/LTR detection per block
727
- - Comprehensive dark mode CSS variable overrides
728
- - Debounced onChange with requestIdleCallback scheduling
729
- - Performance-optimized MutationObserver for direction tracking
730
-
731
- ### v1.1.0
732
- - Initial stable release with 18 block tools
733
- - PresentationStyle variant
734
- - 4 size presets
735
- - Imperative ref API