@byline/ui 0.9.3

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 (368) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +17 -0
  3. package/dist/admin/components/admin-account/change-password.d.ts +9 -0
  4. package/dist/admin/components/admin-account/change-password.d.ts.map +1 -0
  5. package/dist/admin/components/admin-account/change-password.js +192 -0
  6. package/dist/admin/components/admin-account/change-password.module.js +8 -0
  7. package/dist/admin/components/admin-account/change-password_module.css +27 -0
  8. package/dist/admin/components/admin-account/container.d.ts +30 -0
  9. package/dist/admin/components/admin-account/container.d.ts.map +1 -0
  10. package/dist/admin/components/admin-account/container.js +299 -0
  11. package/dist/admin/components/admin-account/container.module.js +28 -0
  12. package/dist/admin/components/admin-account/container_module.css +106 -0
  13. package/dist/admin/components/admin-account/update.d.ts +9 -0
  14. package/dist/admin/components/admin-account/update.d.ts.map +1 -0
  15. package/dist/admin/components/admin-account/update.js +207 -0
  16. package/dist/admin/components/admin-account/update.module.js +8 -0
  17. package/dist/admin/components/admin-account/update_module.css +27 -0
  18. package/dist/admin/components/admin-permissions/inspector.d.ts +5 -0
  19. package/dist/admin/components/admin-permissions/inspector.d.ts.map +1 -0
  20. package/dist/admin/components/admin-permissions/inspector.js +284 -0
  21. package/dist/admin/components/admin-permissions/inspector.module.js +56 -0
  22. package/dist/admin/components/admin-permissions/inspector_module.css +238 -0
  23. package/dist/admin/components/admin-roles/create.d.ts +8 -0
  24. package/dist/admin/components/admin-roles/create.d.ts.map +1 -0
  25. package/dist/admin/components/admin-roles/create.js +177 -0
  26. package/dist/admin/components/admin-roles/create.module.js +8 -0
  27. package/dist/admin/components/admin-roles/create_module.css +27 -0
  28. package/dist/admin/components/admin-roles/permissions.d.ts +11 -0
  29. package/dist/admin/components/admin-roles/permissions.d.ts.map +1 -0
  30. package/dist/admin/components/admin-roles/permissions.js +303 -0
  31. package/dist/admin/components/admin-roles/permissions.module.js +44 -0
  32. package/dist/admin/components/admin-roles/permissions_module.css +192 -0
  33. package/dist/admin/components/admin-roles/update.d.ts +9 -0
  34. package/dist/admin/components/admin-roles/update.d.ts.map +1 -0
  35. package/dist/admin/components/admin-roles/update.js +166 -0
  36. package/dist/admin/components/admin-roles/update.module.js +8 -0
  37. package/dist/admin/components/admin-roles/update_module.css +27 -0
  38. package/dist/admin/components/admin-users/create.d.ts +9 -0
  39. package/dist/admin/components/admin-users/create.d.ts.map +1 -0
  40. package/dist/admin/components/admin-users/create.js +268 -0
  41. package/dist/admin/components/admin-users/create.module.js +10 -0
  42. package/dist/admin/components/admin-users/create_module.css +45 -0
  43. package/dist/admin/components/admin-users/roles.d.ts +12 -0
  44. package/dist/admin/components/admin-users/roles.d.ts.map +1 -0
  45. package/dist/admin/components/admin-users/roles.js +148 -0
  46. package/dist/admin/components/admin-users/roles.module.js +18 -0
  47. package/dist/admin/components/admin-users/roles_module.css +75 -0
  48. package/dist/admin/components/admin-users/set-password.d.ts +9 -0
  49. package/dist/admin/components/admin-users/set-password.d.ts.map +1 -0
  50. package/dist/admin/components/admin-users/set-password.js +170 -0
  51. package/dist/admin/components/admin-users/set-password.module.js +9 -0
  52. package/dist/admin/components/admin-users/set-password_module.css +31 -0
  53. package/dist/admin/components/admin-users/update.d.ts +9 -0
  54. package/dist/admin/components/admin-users/update.d.ts.map +1 -0
  55. package/dist/admin/components/admin-users/update.js +254 -0
  56. package/dist/admin/components/admin-users/update.module.js +9 -0
  57. package/dist/admin/components/admin-users/update_module.css +34 -0
  58. package/dist/admin/components/auth/sign-in-form.d.ts +14 -0
  59. package/dist/admin/components/auth/sign-in-form.d.ts.map +1 -0
  60. package/dist/admin/components/auth/sign-in-form.js +107 -0
  61. package/dist/admin/components/auth/sign-in-form.module.js +10 -0
  62. package/dist/admin/components/auth/sign-in-form_module.css +35 -0
  63. package/dist/admin/components/collections/diff-modal.d.ts +23 -0
  64. package/dist/admin/components/collections/diff-modal.d.ts.map +1 -0
  65. package/dist/admin/components/collections/diff-modal.js +147 -0
  66. package/dist/admin/components/collections/diff-modal.module.js +14 -0
  67. package/dist/admin/components/collections/diff-modal_module.css +56 -0
  68. package/dist/admin/components/collections/status-badge.d.ts +26 -0
  69. package/dist/admin/components/collections/status-badge.d.ts.map +1 -0
  70. package/dist/admin/components/collections/status-badge.js +35 -0
  71. package/dist/admin/components/collections/status-badge.module.js +7 -0
  72. package/dist/admin/components/collections/status-badge_module.css +20 -0
  73. package/dist/admin/group.d.ts +28 -0
  74. package/dist/admin/group.d.ts.map +1 -0
  75. package/dist/admin/group.js +14 -0
  76. package/dist/admin/group.module.js +6 -0
  77. package/dist/admin/group_module.css +19 -0
  78. package/dist/admin/row.d.ts +26 -0
  79. package/dist/admin/row.d.ts.map +1 -0
  80. package/dist/admin/row.js +8 -0
  81. package/dist/admin/row.module.js +5 -0
  82. package/dist/admin/row_module.css +18 -0
  83. package/dist/admin/tabs.d.ts +33 -0
  84. package/dist/admin/tabs.d.ts.map +1 -0
  85. package/dist/admin/tabs.js +34 -0
  86. package/dist/admin/tabs.module.js +10 -0
  87. package/dist/admin/tabs_module.css +68 -0
  88. package/dist/dnd/draggable-sortable/demo/draggable-list-demo.js +105 -0
  89. package/dist/dnd/draggable-sortable/demo/draggable-list-demo.module.js +12 -0
  90. package/dist/dnd/draggable-sortable/demo/draggable-list-demo_module.css +39 -0
  91. package/dist/dnd/draggable-sortable/draggable-sortable-item/index.d.ts +19 -0
  92. package/dist/dnd/draggable-sortable/draggable-sortable-item/index.d.ts.map +1 -0
  93. package/dist/dnd/draggable-sortable/draggable-sortable-item/index.js +27 -0
  94. package/dist/dnd/draggable-sortable/draggable-sortable-item/types.d.ts +25 -0
  95. package/dist/dnd/draggable-sortable/draggable-sortable-item/types.d.ts.map +1 -0
  96. package/dist/dnd/draggable-sortable/draggable-sortable-item/types.js +1 -0
  97. package/dist/dnd/draggable-sortable/draggable-sortable.d.ts +17 -0
  98. package/dist/dnd/draggable-sortable/draggable-sortable.d.ts.map +1 -0
  99. package/dist/dnd/draggable-sortable/draggable-sortable.js +46 -0
  100. package/dist/dnd/draggable-sortable/index.d.ts +5 -0
  101. package/dist/dnd/draggable-sortable/index.d.ts.map +1 -0
  102. package/dist/dnd/draggable-sortable/index.js +4 -0
  103. package/dist/dnd/draggable-sortable/types.d.ts +26 -0
  104. package/dist/dnd/draggable-sortable/types.d.ts.map +1 -0
  105. package/dist/dnd/draggable-sortable/types.js +1 -0
  106. package/dist/dnd/draggable-sortable/use-draggable-sortable/index.d.ts +16 -0
  107. package/dist/dnd/draggable-sortable/use-draggable-sortable/index.d.ts.map +1 -0
  108. package/dist/dnd/draggable-sortable/use-draggable-sortable/index.js +28 -0
  109. package/dist/dnd/draggable-sortable/use-draggable-sortable/types.d.ts +23 -0
  110. package/dist/dnd/draggable-sortable/use-draggable-sortable/types.d.ts.map +1 -0
  111. package/dist/dnd/draggable-sortable/use-draggable-sortable/types.js +1 -0
  112. package/dist/dnd/draggable-sortable/utils.d.ts +14 -0
  113. package/dist/dnd/draggable-sortable/utils.d.ts.map +1 -0
  114. package/dist/dnd/draggable-sortable/utils.js +10 -0
  115. package/dist/fields/array/array-field.d.ts +15 -0
  116. package/dist/fields/array/array-field.d.ts.map +1 -0
  117. package/dist/fields/array/array-field.js +176 -0
  118. package/dist/fields/array/array-field.module.js +11 -0
  119. package/dist/fields/array/array-field_module.css +32 -0
  120. package/dist/fields/blocks/blocks-field.d.ts +14 -0
  121. package/dist/fields/blocks/blocks-field.d.ts.map +1 -0
  122. package/dist/fields/blocks/blocks-field.js +244 -0
  123. package/dist/fields/blocks/blocks-field.module.js +26 -0
  124. package/dist/fields/blocks/blocks-field_module.css +107 -0
  125. package/dist/fields/checkbox/checkbox-field.d.ts +17 -0
  126. package/dist/fields/checkbox/checkbox-field.d.ts.map +1 -0
  127. package/dist/fields/checkbox/checkbox-field.js +27 -0
  128. package/dist/fields/column-formatter.d.ts +21 -0
  129. package/dist/fields/column-formatter.d.ts.map +1 -0
  130. package/dist/fields/column-formatter.js +15 -0
  131. package/dist/fields/date-time-formatter.d.ts +17 -0
  132. package/dist/fields/date-time-formatter.d.ts.map +1 -0
  133. package/dist/fields/date-time-formatter.js +8 -0
  134. package/dist/fields/datetime/datetime-field.d.ts +17 -0
  135. package/dist/fields/datetime/datetime-field.d.ts.map +1 -0
  136. package/dist/fields/datetime/datetime-field.js +37 -0
  137. package/dist/fields/datetime/datetime-field.module.js +5 -0
  138. package/dist/fields/datetime/datetime-field_module.css +4 -0
  139. package/dist/fields/draggable-context-menu.d.ts +7 -0
  140. package/dist/fields/draggable-context-menu.d.ts.map +1 -0
  141. package/dist/fields/draggable-context-menu.js +83 -0
  142. package/dist/fields/draggable-context-menu.module.js +15 -0
  143. package/dist/fields/draggable-context-menu_module.css +91 -0
  144. package/dist/fields/field-helpers.d.ts +27 -0
  145. package/dist/fields/field-helpers.d.ts.map +1 -0
  146. package/dist/fields/field-helpers.js +48 -0
  147. package/dist/fields/field-renderer.d.ts +31 -0
  148. package/dist/fields/field-renderer.d.ts.map +1 -0
  149. package/dist/fields/field-renderer.js +189 -0
  150. package/dist/fields/field-renderer.module.js +8 -0
  151. package/dist/fields/field-renderer_module.css +11 -0
  152. package/dist/fields/file/file-field.d.ts +18 -0
  153. package/dist/fields/file/file-field.d.ts.map +1 -0
  154. package/dist/fields/file/file-field.js +125 -0
  155. package/dist/fields/file/file-field.module.js +13 -0
  156. package/dist/fields/file/file-field_module.css +64 -0
  157. package/dist/fields/group/group-field.d.ts +16 -0
  158. package/dist/fields/group/group-field.d.ts.map +1 -0
  159. package/dist/fields/group/group-field.js +59 -0
  160. package/dist/fields/group/group-field.module.js +9 -0
  161. package/dist/fields/group/group-field_module.css +27 -0
  162. package/dist/fields/image/image-field.d.ts +20 -0
  163. package/dist/fields/image/image-field.d.ts.map +1 -0
  164. package/dist/fields/image/image-field.js +198 -0
  165. package/dist/fields/image/image-field.module.js +21 -0
  166. package/dist/fields/image/image-field_module.css +96 -0
  167. package/dist/fields/image/image-upload-field.d.ts +22 -0
  168. package/dist/fields/image/image-upload-field.d.ts.map +1 -0
  169. package/dist/fields/image/image-upload-field.js +187 -0
  170. package/dist/fields/image/image-upload-field.module.js +19 -0
  171. package/dist/fields/image/image-upload-field_module.css +92 -0
  172. package/dist/fields/local-date-time.d.ts +28 -0
  173. package/dist/fields/local-date-time.d.ts.map +1 -0
  174. package/dist/fields/local-date-time.js +49 -0
  175. package/dist/fields/locale-badge.d.ts +19 -0
  176. package/dist/fields/locale-badge.d.ts.map +1 -0
  177. package/dist/fields/locale-badge.js +10 -0
  178. package/dist/fields/locale-badge.module.js +5 -0
  179. package/dist/fields/locale-badge_module.css +27 -0
  180. package/dist/fields/numerical/numerical-field.d.ts +19 -0
  181. package/dist/fields/numerical/numerical-field.d.ts.map +1 -0
  182. package/dist/fields/numerical/numerical-field.js +73 -0
  183. package/dist/fields/relation/relation-display.d.ts +41 -0
  184. package/dist/fields/relation/relation-display.d.ts.map +1 -0
  185. package/dist/fields/relation/relation-display.js +58 -0
  186. package/dist/fields/relation/relation-display.module.js +9 -0
  187. package/dist/fields/relation/relation-display_module.css +21 -0
  188. package/dist/fields/relation/relation-field.d.ts +19 -0
  189. package/dist/fields/relation/relation-field.d.ts.map +1 -0
  190. package/dist/fields/relation/relation-field.js +133 -0
  191. package/dist/fields/relation/relation-field.module.js +13 -0
  192. package/dist/fields/relation/relation-field_module.css +62 -0
  193. package/dist/fields/relation/relation-picker.d.ts +50 -0
  194. package/dist/fields/relation/relation-picker.d.ts.map +1 -0
  195. package/dist/fields/relation/relation-picker.js +233 -0
  196. package/dist/fields/relation/relation-picker.module.js +26 -0
  197. package/dist/fields/relation/relation-picker_module.css +124 -0
  198. package/dist/fields/relation/relation-summary.d.ts +32 -0
  199. package/dist/fields/relation/relation-summary.d.ts.map +1 -0
  200. package/dist/fields/relation/relation-summary.js +50 -0
  201. package/dist/fields/relation/relation-summary.module.js +11 -0
  202. package/dist/fields/relation/relation-summary_module.css +37 -0
  203. package/dist/fields/select/select-field.d.ts +17 -0
  204. package/dist/fields/select/select-field.d.ts.map +1 -0
  205. package/dist/fields/select/select-field.js +42 -0
  206. package/dist/fields/select/select-field.module.js +5 -0
  207. package/dist/fields/select/select-field_module.css +4 -0
  208. package/dist/fields/sortable-item.d.ts +16 -0
  209. package/dist/fields/sortable-item.d.ts.map +1 -0
  210. package/dist/fields/sortable-item.js +80 -0
  211. package/dist/fields/sortable-item.module.js +22 -0
  212. package/dist/fields/sortable-item_module.css +124 -0
  213. package/dist/fields/text/text-field.d.ts +21 -0
  214. package/dist/fields/text/text-field.d.ts.map +1 -0
  215. package/dist/fields/text/text-field.js +104 -0
  216. package/dist/fields/text/text-field.module.js +6 -0
  217. package/dist/fields/text/text-field_module.css +5 -0
  218. package/dist/fields/text-area/text-area-field.d.ts +21 -0
  219. package/dist/fields/text-area/text-area-field.d.ts.map +1 -0
  220. package/dist/fields/text-area/text-area-field.js +105 -0
  221. package/dist/fields/text-area/text-area-field.module.js +6 -0
  222. package/dist/fields/text-area/text-area-field_module.css +5 -0
  223. package/dist/fields/use-field-change-handler.d.ts +24 -0
  224. package/dist/fields/use-field-change-handler.d.ts.map +1 -0
  225. package/dist/fields/use-field-change-handler.js +52 -0
  226. package/dist/forms/document-actions.d.ts +14 -0
  227. package/dist/forms/document-actions.d.ts.map +1 -0
  228. package/dist/forms/document-actions.js +153 -0
  229. package/dist/forms/document-actions.module.js +18 -0
  230. package/dist/forms/document-actions_module.css +66 -0
  231. package/dist/forms/form-context.d.ts +78 -0
  232. package/dist/forms/form-context.d.ts.map +1 -0
  233. package/dist/forms/form-context.js +420 -0
  234. package/dist/forms/form-renderer.d.ts +66 -0
  235. package/dist/forms/form-renderer.d.ts.map +1 -0
  236. package/dist/forms/form-renderer.js +555 -0
  237. package/dist/forms/form-renderer.module.js +46 -0
  238. package/dist/forms/form-renderer_module.css +242 -0
  239. package/dist/forms/navigation-guard.d.ts +55 -0
  240. package/dist/forms/navigation-guard.d.ts.map +1 -0
  241. package/dist/forms/navigation-guard.js +22 -0
  242. package/dist/forms/path-widget.d.ts +33 -0
  243. package/dist/forms/path-widget.d.ts.map +1 -0
  244. package/dist/forms/path-widget.js +101 -0
  245. package/dist/forms/path-widget.module.js +8 -0
  246. package/dist/forms/path-widget_module.css +29 -0
  247. package/dist/forms/upload-executor.d.ts +58 -0
  248. package/dist/forms/upload-executor.d.ts.map +1 -0
  249. package/dist/forms/upload-executor.js +92 -0
  250. package/dist/react.d.ts +55 -0
  251. package/dist/react.d.ts.map +1 -0
  252. package/dist/react.js +48 -0
  253. package/dist/services/admin-services-context.d.ts +17 -0
  254. package/dist/services/admin-services-context.d.ts.map +1 -0
  255. package/dist/services/admin-services-context.js +13 -0
  256. package/dist/services/admin-services-types.d.ts +130 -0
  257. package/dist/services/admin-services-types.d.ts.map +1 -0
  258. package/dist/services/admin-services-types.js +1 -0
  259. package/dist/services/field-services-context.d.ts +17 -0
  260. package/dist/services/field-services-context.d.ts.map +1 -0
  261. package/dist/services/field-services-context.js +13 -0
  262. package/dist/services/field-services-types.d.ts +64 -0
  263. package/dist/services/field-services-types.d.ts.map +1 -0
  264. package/dist/services/field-services-types.js +1 -0
  265. package/package.json +133 -0
  266. package/src/admin/components/admin-account/change-password.module.css +40 -0
  267. package/src/admin/components/admin-account/change-password.tsx +232 -0
  268. package/src/admin/components/admin-account/container.module.css +158 -0
  269. package/src/admin/components/admin-account/container.tsx +230 -0
  270. package/src/admin/components/admin-account/update.module.css +40 -0
  271. package/src/admin/components/admin-account/update.tsx +263 -0
  272. package/src/admin/components/admin-permissions/inspector.module.css +326 -0
  273. package/src/admin/components/admin-permissions/inspector.tsx +298 -0
  274. package/src/admin/components/admin-roles/create.module.css +40 -0
  275. package/src/admin/components/admin-roles/create.tsx +218 -0
  276. package/src/admin/components/admin-roles/permissions.module.css +279 -0
  277. package/src/admin/components/admin-roles/permissions.tsx +396 -0
  278. package/src/admin/components/admin-roles/update.module.css +40 -0
  279. package/src/admin/components/admin-roles/update.tsx +218 -0
  280. package/src/admin/components/admin-users/create.module.css +63 -0
  281. package/src/admin/components/admin-users/create.tsx +323 -0
  282. package/src/admin/components/admin-users/roles.module.css +119 -0
  283. package/src/admin/components/admin-users/roles.tsx +172 -0
  284. package/src/admin/components/admin-users/set-password.module.css +46 -0
  285. package/src/admin/components/admin-users/set-password.tsx +199 -0
  286. package/src/admin/components/admin-users/update.module.css +49 -0
  287. package/src/admin/components/admin-users/update.tsx +328 -0
  288. package/src/admin/components/auth/sign-in-form.module.css +53 -0
  289. package/src/admin/components/auth/sign-in-form.tsx +118 -0
  290. package/src/admin/components/collections/diff-modal.module.css +79 -0
  291. package/src/admin/components/collections/diff-modal.tsx +171 -0
  292. package/src/admin/components/collections/status-badge.module.css +31 -0
  293. package/src/admin/components/collections/status-badge.tsx +69 -0
  294. package/src/admin/group.module.css +41 -0
  295. package/src/admin/group.tsx +40 -0
  296. package/src/admin/row.module.css +32 -0
  297. package/src/admin/row.tsx +33 -0
  298. package/src/admin/tabs.module.css +107 -0
  299. package/src/admin/tabs.tsx +74 -0
  300. package/src/declarations.d.ts +4 -0
  301. package/src/dnd/draggable-sortable/demo/draggable-list-demo.module.css +65 -0
  302. package/src/dnd/draggable-sortable/demo/draggable-list-demo.tsx +117 -0
  303. package/src/dnd/draggable-sortable/draggable-sortable-item/index.tsx +54 -0
  304. package/src/dnd/draggable-sortable/draggable-sortable-item/types.ts +30 -0
  305. package/src/dnd/draggable-sortable/draggable-sortable.tsx +86 -0
  306. package/src/dnd/draggable-sortable/index.ts +5 -0
  307. package/src/dnd/draggable-sortable/types.ts +24 -0
  308. package/src/dnd/draggable-sortable/use-draggable-sortable/index.tsx +50 -0
  309. package/src/dnd/draggable-sortable/use-draggable-sortable/types.ts +25 -0
  310. package/src/dnd/draggable-sortable/utils.ts +29 -0
  311. package/src/fields/array/array-field.module.css +48 -0
  312. package/src/fields/array/array-field.tsx +266 -0
  313. package/src/fields/blocks/blocks-field.module.css +148 -0
  314. package/src/fields/blocks/blocks-field.tsx +312 -0
  315. package/src/fields/checkbox/checkbox-field.tsx +53 -0
  316. package/src/fields/column-formatter.tsx +31 -0
  317. package/src/fields/date-time-formatter.tsx +22 -0
  318. package/src/fields/datetime/datetime-field.module.css +13 -0
  319. package/src/fields/datetime/datetime-field.tsx +54 -0
  320. package/src/fields/draggable-context-menu.module.css +127 -0
  321. package/src/fields/draggable-context-menu.tsx +85 -0
  322. package/src/fields/field-helpers.ts +66 -0
  323. package/src/fields/field-renderer.module.css +22 -0
  324. package/src/fields/field-renderer.tsx +255 -0
  325. package/src/fields/file/file-field.module.css +88 -0
  326. package/src/fields/file/file-field.tsx +107 -0
  327. package/src/fields/group/group-field.module.css +43 -0
  328. package/src/fields/group/group-field.tsx +84 -0
  329. package/src/fields/image/image-field.module.css +129 -0
  330. package/src/fields/image/image-field.tsx +212 -0
  331. package/src/fields/image/image-upload-field.module.css +123 -0
  332. package/src/fields/image/image-upload-field.tsx +270 -0
  333. package/src/fields/local-date-time.tsx +88 -0
  334. package/src/fields/locale-badge.module.css +37 -0
  335. package/src/fields/locale-badge.tsx +32 -0
  336. package/src/fields/numerical/numerical-field.tsx +112 -0
  337. package/src/fields/relation/relation-display.module.css +36 -0
  338. package/src/fields/relation/relation-display.tsx +130 -0
  339. package/src/fields/relation/relation-field.module.css +83 -0
  340. package/src/fields/relation/relation-field.tsx +202 -0
  341. package/src/fields/relation/relation-picker.module.css +168 -0
  342. package/src/fields/relation/relation-picker.tsx +325 -0
  343. package/src/fields/relation/relation-summary.module.css +55 -0
  344. package/src/fields/relation/relation-summary.tsx +123 -0
  345. package/src/fields/select/select-field.module.css +13 -0
  346. package/src/fields/select/select-field.tsx +56 -0
  347. package/src/fields/sortable-item.module.css +167 -0
  348. package/src/fields/sortable-item.tsx +101 -0
  349. package/src/fields/text/text-field.module.css +13 -0
  350. package/src/fields/text/text-field.tsx +146 -0
  351. package/src/fields/text-area/text-area-field.module.css +13 -0
  352. package/src/fields/text-area/text-area-field.tsx +147 -0
  353. package/src/fields/use-field-change-handler.ts +112 -0
  354. package/src/forms/document-actions.module.css +94 -0
  355. package/src/forms/document-actions.tsx +149 -0
  356. package/src/forms/form-context.tsx +620 -0
  357. package/src/forms/form-renderer.module.css +318 -0
  358. package/src/forms/form-renderer.tsx +786 -0
  359. package/src/forms/navigation-guard.tsx +98 -0
  360. package/src/forms/path-widget.module.css +41 -0
  361. package/src/forms/path-widget.test.tsx +217 -0
  362. package/src/forms/path-widget.tsx +141 -0
  363. package/src/forms/upload-executor.ts +190 -0
  364. package/src/react.ts +79 -0
  365. package/src/services/admin-services-context.tsx +35 -0
  366. package/src/services/admin-services-types.ts +177 -0
  367. package/src/services/field-services-context.tsx +35 -0
  368. package/src/services/field-services-types.ts +68 -0
@@ -0,0 +1,312 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ import { useEffect, useMemo, useState } from 'react'
10
+
11
+ import type {
12
+ BlocksField as BlocksFieldType,
13
+ Field,
14
+ GroupField as GroupFieldType,
15
+ } from '@byline/core'
16
+ import { Card, CloseIcon, IconButton, Modal, PlusIcon } from '@infonomic/uikit/react'
17
+ import cx from 'classnames'
18
+
19
+ import { DraggableSortable, moveItem } from '../../dnd/draggable-sortable'
20
+ import { defaultScalarForField } from '../../fields/field-helpers'
21
+ import { GroupField } from '../../fields/group/group-field'
22
+ import { SortableItem } from '../../fields/sortable-item'
23
+ import { useFormContext } from '../../forms/form-context'
24
+ import styles from './blocks-field.module.css'
25
+
26
+ // ---------------------------------------------------------------------------
27
+ // BlocksField — renders `type: 'blocks'` fields. Children are heterogeneous
28
+ // group fields selected via a modal picker. Supports D&D.
29
+ // ---------------------------------------------------------------------------
30
+
31
+ export const BlocksField = ({
32
+ field,
33
+ defaultValue,
34
+ path,
35
+ }: {
36
+ field: BlocksFieldType
37
+ defaultValue: any
38
+ path: string
39
+ }) => {
40
+ const { appendPatch, getFieldValue, getFieldValues, setFieldStore } = useFormContext()
41
+ const [items, setItems] = useState<{ id: string; data: any }[]>([])
42
+ const [showAddBlockModal, setShowAddBlockModal] = useState(false)
43
+ const [pendingInsertIndex, setPendingInsertIndex] = useState<number | null>(null)
44
+
45
+ const availableBlocks = useMemo(() => field.blocks ?? [], [field.blocks])
46
+ const [selectedBlockName, setSelectedBlockName] = useState<string>(
47
+ () => availableBlocks[0]?.blockType
48
+ )
49
+
50
+ useEffect(() => {
51
+ if (
52
+ selectedBlockName == null ||
53
+ !availableBlocks.some((b) => b.blockType === selectedBlockName)
54
+ ) {
55
+ setSelectedBlockName(availableBlocks[0]?.blockType)
56
+ }
57
+ }, [availableBlocks, selectedBlockName])
58
+
59
+ useEffect(() => {
60
+ if (Array.isArray(defaultValue)) {
61
+ setItems(
62
+ defaultValue.map((item: any) => ({
63
+ id:
64
+ item && typeof item === 'object' && '_id' in item
65
+ ? String((item as { _id: string })._id)
66
+ : crypto.randomUUID(),
67
+ data: item,
68
+ }))
69
+ )
70
+ } else {
71
+ setItems([])
72
+ }
73
+ }, [defaultValue])
74
+
75
+ const handleDragEnd = ({
76
+ moveFromIndex,
77
+ moveToIndex,
78
+ }: {
79
+ moveFromIndex: number
80
+ moveToIndex: number
81
+ }) => {
82
+ setItems((prev) => moveItem(prev, moveFromIndex, moveToIndex))
83
+ const currentArray = (getFieldValue(path) ?? defaultValue) as any[]
84
+
85
+ if (Array.isArray(currentArray)) {
86
+ const clampedFrom = Math.max(0, Math.min(moveFromIndex, currentArray.length - 1))
87
+ const clampedTo = Math.max(0, Math.min(moveToIndex, currentArray.length - 1))
88
+ if (clampedFrom === clampedTo) return
89
+
90
+ const item = currentArray[clampedFrom]
91
+ const itemId =
92
+ item && typeof item === 'object' && '_id' in item
93
+ ? String((item as { _id: string })._id)
94
+ : String(clampedFrom)
95
+
96
+ appendPatch({
97
+ kind: 'array.move',
98
+ path: path,
99
+ itemId,
100
+ toIndex: clampedTo,
101
+ })
102
+ }
103
+ }
104
+
105
+ const handleAddItem = async (forcedVariantName?: string, atIndex?: number) => {
106
+ setShowAddBlockModal(false)
107
+ setPendingInsertIndex(null)
108
+
109
+ const variant =
110
+ (forcedVariantName != null
111
+ ? availableBlocks.find((v) => v.blockType === forcedVariantName)
112
+ : undefined) ?? availableBlocks[0]
113
+
114
+ if (!variant) return
115
+
116
+ const compositeFields = (variant.fields ?? []) as Field[]
117
+
118
+ const newId = crypto.randomUUID()
119
+ const newItem: Record<string, any> = {
120
+ _id: newId,
121
+ _type: variant.blockType,
122
+ }
123
+ for (const f of compositeFields) {
124
+ newItem[f.name] = await defaultScalarForField(f, getFieldValues)
125
+ }
126
+
127
+ const currentArray = (getFieldValue(path) ?? defaultValue) as any[]
128
+ const insertAt = atIndex != null ? atIndex : currentArray ? currentArray.length : 0
129
+
130
+ const newItemWrapper = { id: newId, data: newItem }
131
+ setItems((prev) => {
132
+ const next = [...prev]
133
+ next.splice(insertAt, 0, newItemWrapper)
134
+ return next
135
+ })
136
+
137
+ appendPatch({
138
+ kind: 'array.insert',
139
+ path: path,
140
+ index: insertAt,
141
+ item: newItem,
142
+ })
143
+
144
+ const newArrayValue = currentArray ? [...currentArray] : []
145
+ newArrayValue.splice(insertAt, 0, newItem)
146
+ setFieldStore(path, newArrayValue)
147
+ }
148
+
149
+ const handleRemoveItem = (index: number) => {
150
+ const currentArray = (getFieldValue(path) ?? defaultValue) as any[]
151
+ if (!Array.isArray(currentArray) || index < 0 || index >= currentArray.length) return
152
+
153
+ const item = currentArray[index]
154
+ const itemId =
155
+ item && typeof item === 'object' && '_id' in item
156
+ ? String((item as { _id: string })._id)
157
+ : String(index)
158
+
159
+ setItems((prev) => prev.filter((_, i) => i !== index))
160
+
161
+ appendPatch({
162
+ kind: 'array.remove',
163
+ path: path,
164
+ itemId,
165
+ })
166
+
167
+ const newArrayValue = [...currentArray]
168
+ newArrayValue.splice(index, 1)
169
+ setFieldStore(path, newArrayValue)
170
+ }
171
+
172
+ const handleInsertBelow = (index: number, forcedVariantName?: string) => {
173
+ if (availableBlocks.length > 1 && forcedVariantName == null) {
174
+ setPendingInsertIndex(index + 1)
175
+ setShowAddBlockModal(true)
176
+ } else {
177
+ void handleAddItem(forcedVariantName, index + 1)
178
+ }
179
+ }
180
+
181
+ const renderItem = (itemWrapper: { id: string; data: any }, index: number) => {
182
+ const item = itemWrapper.data
183
+ const arrayElementPath = `${path}[${index}]`
184
+
185
+ if (!item || typeof item !== 'object' || typeof item._type !== 'string') return null
186
+
187
+ const subField = field.blocks?.find((b) => b.blockType === item._type)
188
+ if (subField == null) return null
189
+
190
+ // Extract field data (everything except _id and _type)
191
+ const { _id, _type, ...fieldData } = item
192
+ const label = subField.label ?? _type
193
+
194
+ // Render the block's children directly with arrayElementPath as the
195
+ // path (not basePath). FieldRenderer would append the group name
196
+ // (e.g. "richTextBlock") producing paths like
197
+ // "content[0].richTextBlock.constrainedWidth", but the flat block
198
+ // shape stores fields directly on the item so the correct path is
199
+ // "content[0].constrainedWidth".
200
+ const body = (
201
+ <GroupField
202
+ key={subField.blockType}
203
+ field={
204
+ {
205
+ type: 'group',
206
+ name: subField.blockType,
207
+ fields: subField.fields,
208
+ label: undefined,
209
+ } as GroupFieldType
210
+ }
211
+ defaultValue={fieldData}
212
+ path={arrayElementPath}
213
+ />
214
+ )
215
+
216
+ return (
217
+ <SortableItem
218
+ key={itemWrapper.id}
219
+ id={itemWrapper.id}
220
+ label={label ?? subField.blockType}
221
+ onAddBelow={() => handleInsertBelow(index)}
222
+ onRemove={() => handleRemoveItem(index)}
223
+ >
224
+ {body}
225
+ </SortableItem>
226
+ )
227
+ }
228
+
229
+ return (
230
+ <div className={`byline-field-blocks ${field.name}`}>
231
+ {field.label && (
232
+ <h3 className={cx('byline-field-blocks-title', styles.title)}>{field.label}</h3>
233
+ )}
234
+ <DraggableSortable
235
+ ids={items.map((i) => i.id)}
236
+ onDragEnd={handleDragEnd}
237
+ className={cx('byline-field-blocks-stack', styles.stack)}
238
+ >
239
+ {items.map((item, index) => renderItem(item, index))}
240
+ <div className={cx('byline-field-blocks-add-row', styles['add-row'])}>
241
+ <IconButton
242
+ onClick={() => {
243
+ setPendingInsertIndex(null)
244
+ setShowAddBlockModal(true)
245
+ }}
246
+ disabled={!selectedBlockName}
247
+ aria-label="Add block"
248
+ >
249
+ <PlusIcon />
250
+ </IconButton>
251
+ </div>
252
+ </DraggableSortable>
253
+ <Modal
254
+ isOpen={showAddBlockModal}
255
+ closeOnOverlayClick={true}
256
+ onDismiss={() => {
257
+ setShowAddBlockModal(false)
258
+ setPendingInsertIndex(null)
259
+ }}
260
+ >
261
+ <Modal.Container style={{ maxWidth: '600px' }}>
262
+ <Modal.Header className={cx('byline-field-blocks-modal-head', styles['modal-head'])}>
263
+ <h3 className={cx('byline-field-blocks-modal-title', styles['modal-title'])}>Blocks</h3>
264
+ <IconButton
265
+ arial-label="Close"
266
+ size="xs"
267
+ onClick={() => {
268
+ setShowAddBlockModal(false)
269
+ setPendingInsertIndex(null)
270
+ }}
271
+ >
272
+ <CloseIcon width="16px" height="16px" svgClassName="white-icon" />
273
+ </IconButton>
274
+ </Modal.Header>
275
+ <Modal.Content className={cx('byline-field-blocks-card-cursor', styles['modal-content'])}>
276
+ <div className={cx('byline-field-blocks-grid', styles.grid)}>
277
+ {availableBlocks.map((b, index) => (
278
+ <Card
279
+ key={b.blockType}
280
+ hover
281
+ onClick={() => void handleAddItem(b.blockType, pendingInsertIndex ?? undefined)}
282
+ className={cx('byline-field-blocks-card', styles.card)}
283
+ >
284
+ <Card.Header>
285
+ <div className={cx('byline-field-blocks-card-head', styles['card-head'])}>
286
+ <Card.Title
287
+ className={cx('byline-field-blocks-card-title', styles['card-title'])}
288
+ >
289
+ {b.label ?? b.blockType}
290
+ </Card.Title>
291
+ <span className={cx('byline-field-blocks-card-index', styles['card-index'])}>
292
+ {index + 1}
293
+ </span>
294
+ </div>
295
+ <code className={cx('byline-field-blocks-card-code', styles['card-code'])}>
296
+ {b.blockType}
297
+ </code>
298
+ </Card.Header>
299
+ <Card.Content>
300
+ <p className={cx('byline-field-blocks-card-body', styles['card-body'])}>
301
+ {b.helpText ?? b.label ?? b.blockType}
302
+ </p>
303
+ </Card.Content>
304
+ </Card>
305
+ ))}
306
+ </div>
307
+ </Modal.Content>
308
+ </Modal.Container>
309
+ </Modal>
310
+ </div>
311
+ )
312
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ import type { CheckboxField as FieldType } from '@byline/core'
10
+ import { Checkbox } from '@infonomic/uikit/react'
11
+
12
+ import { useFieldError, useFieldValue } from '../../forms/form-context'
13
+
14
+ export const CheckboxField = ({
15
+ field,
16
+ value,
17
+ defaultValue,
18
+ onChange,
19
+ id,
20
+ path,
21
+ }: {
22
+ field: FieldType
23
+ value?: boolean
24
+ defaultValue?: boolean
25
+ onChange?: (value: boolean) => void
26
+ id?: string
27
+ path?: string
28
+ }) => {
29
+ const fieldPath = path ?? field.name
30
+ const fieldError = useFieldError(fieldPath)
31
+ const fieldValue = useFieldValue<boolean | undefined>(fieldPath)
32
+ const checked = value ?? fieldValue ?? defaultValue ?? false
33
+
34
+ return (
35
+ <div className={`byline-field-checkbox ${field.name}`}>
36
+ <Checkbox
37
+ id={id ?? fieldPath}
38
+ name={field.name}
39
+ label={field.label}
40
+ checked={checked}
41
+ size="sm"
42
+ helpText={field.helpText}
43
+ // TODO: Handle indeterminate state
44
+ onCheckedChange={(value: boolean | 'indeterminate') => {
45
+ const next = value === 'indeterminate' ? false : Boolean(value)
46
+ onChange?.(next)
47
+ }}
48
+ error={fieldError != null}
49
+ errorText={fieldError}
50
+ />
51
+ </div>
52
+ )
53
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ import type { ColumnFormatter, FormatterProps } from '@byline/core'
10
+
11
+ /**
12
+ * Type guard: returns true when the formatter is a `{ component }` wrapper
13
+ * rather than a plain function.
14
+ */
15
+ export function isComponentFormatter<T>(
16
+ fmt: ColumnFormatter<T>
17
+ ): fmt is { component: (props: FormatterProps<T>) => any } {
18
+ return typeof fmt === 'object' && fmt !== null && 'component' in fmt
19
+ }
20
+
21
+ /**
22
+ * Render a cell value through its column formatter (if any).
23
+ * Handles both plain-function and `{ component }` formatters.
24
+ */
25
+ export function renderFormatted(value: any, document: any, formatter: ColumnFormatter) {
26
+ if (isComponentFormatter(formatter)) {
27
+ const Component = formatter.component
28
+ return <Component value={value} record={document} />
29
+ }
30
+ return formatter(value, document)
31
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ import type { FormatterProps } from '@byline/core'
10
+
11
+ import { LocalDateTime } from './local-date-time'
12
+
13
+ /**
14
+ * SSR-safe date-time column formatter for list views.
15
+ *
16
+ * Uses the `LocalDateTime` component which renders a placeholder on the server
17
+ * and formats to the user's locale/timezone after hydration, avoiding
18
+ * server/client mismatches.
19
+ */
20
+ export function DateTimeFormatter({ value }: FormatterProps) {
21
+ return <LocalDateTime value={value} />
22
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * DateTimeField — date/time picker form widget.
3
+ *
4
+ * Override handles:
5
+ * .byline-field-datetime — the wrapper div
6
+ * .byline-field-datetime-dirty — added to the inner picker when the
7
+ * field has unsaved local changes
8
+ */
9
+
10
+ .dirty,
11
+ :global(.byline-field-datetime-dirty) {
12
+ border-color: var(--blue-300);
13
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * This Source Code is subject to the terms of the Mozilla Public
3
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+ *
6
+ * Copyright (c) Infonomic Company Limited
7
+ */
8
+
9
+ import type { DateTimeField as FieldType } from '@byline/core'
10
+ import { DatePicker, ErrorText } from '@infonomic/uikit/react'
11
+ import cx from 'classnames'
12
+
13
+ import { useFieldError, useFieldValue, useIsDirty } from '../../forms/form-context'
14
+ import styles from './datetime-field.module.css'
15
+
16
+ export const DateTimeField = ({
17
+ field,
18
+ value,
19
+ defaultValue,
20
+ onChange,
21
+ id,
22
+ path,
23
+ }: {
24
+ field: FieldType
25
+ value?: Date | null
26
+ defaultValue?: Date | null
27
+ onChange?: (value: Date | null) => void
28
+ id?: string
29
+ path?: string
30
+ }) => {
31
+ const fieldPath = path ?? field.name
32
+ const fieldError = useFieldError(fieldPath)
33
+ const isDirty = useIsDirty(fieldPath)
34
+ const fieldValue = useFieldValue<Date | null | undefined>(fieldPath)
35
+ const incomingValue = value ?? fieldValue ?? defaultValue ?? null
36
+
37
+ return (
38
+ <div className={`byline-field-datetime ${field.name}`}>
39
+ <DatePicker
40
+ id={id ?? fieldPath}
41
+ name={field.name}
42
+ label={field.label}
43
+ required={!field.optional}
44
+ initialValue={incomingValue}
45
+ mode={field.mode || 'datetime'}
46
+ yearsInFuture={field.yearsInFuture || 1}
47
+ yearsInPast={field.yearsInPast || 10}
48
+ onDateChange={(date) => onChange?.(date)}
49
+ className={cx(isDirty && ['byline-field-datetime-dirty', styles.dirty])}
50
+ />
51
+ {fieldError && <ErrorText id={`${field.name}-error`} text={fieldError} />}
52
+ </div>
53
+ )
54
+ }
@@ -0,0 +1,127 @@
1
+ /**
2
+ * DraggableContextMenu — small `…` dropdown attached to draggable list rows.
3
+ *
4
+ * Override handles:
5
+ * .byline-draggable-menu — dropdown content panel
6
+ * .byline-draggable-menu-item — individual menu item
7
+ * .byline-draggable-menu-row — flex row inside an item
8
+ * .byline-draggable-menu-icon-slot — fixed-width icon column
9
+ * .byline-draggable-menu-label — label text column
10
+ * .byline-draggable-menu-label-danger — destructive-action label
11
+ * .byline-draggable-menu-separator — separator between items
12
+ */
13
+
14
+ .menu,
15
+ :global(.byline-draggable-menu) {
16
+ z-index: 40;
17
+ width: 8.5rem;
18
+ padding: 0.25rem 0.375rem;
19
+ background-color: white;
20
+ border: var(--border-width-thin) var(--border-style-solid) var(--gray-200);
21
+ border-radius: var(--border-radius-sm);
22
+ box-shadow:
23
+ 0 4px 6px -1px rgb(0 0 0 / 0.1),
24
+ 0 2px 4px -2px rgb(0 0 0 / 0.1);
25
+ }
26
+
27
+ .item,
28
+ :global(.byline-draggable-menu-item) {
29
+ display: flex;
30
+ align-items: center;
31
+ gap: 0.25rem;
32
+ width: 100%;
33
+ padding: 5px 2px;
34
+ border-radius: var(--border-radius-sm);
35
+ color: var(--gray-600);
36
+ cursor: default;
37
+ user-select: none;
38
+ outline: none;
39
+ }
40
+
41
+ @media (min-width: 48rem) {
42
+ .item,
43
+ :global(.byline-draggable-menu-item) {
44
+ font-size: var(--font-size-sm);
45
+ }
46
+ }
47
+
48
+ .item:hover,
49
+ .item:focus,
50
+ :global(.byline-draggable-menu-item):hover,
51
+ :global(.byline-draggable-menu-item):focus {
52
+ background-color: oklch(from var(--canvas-50) l c h / 0.3);
53
+ }
54
+
55
+ .row,
56
+ :global(.byline-draggable-menu-row) {
57
+ display: flex;
58
+ align-items: center;
59
+ gap: 0.25rem;
60
+ width: 100%;
61
+ }
62
+
63
+ .icon-slot,
64
+ :global(.byline-draggable-menu-icon-slot) {
65
+ display: inline-block;
66
+ width: 22px;
67
+ }
68
+
69
+ .label,
70
+ :global(.byline-draggable-menu-label) {
71
+ display: inline-block;
72
+ flex: 1;
73
+ width: 100%;
74
+ align-self: flex-start;
75
+ text-align: left;
76
+ color: black;
77
+ }
78
+
79
+ .label-danger,
80
+ :global(.byline-draggable-menu-label-danger) {
81
+ color: var(--red-600);
82
+ }
83
+
84
+ .delete-icon,
85
+ :global(.byline-draggable-menu-delete-icon) {
86
+ stroke: var(--red-600);
87
+ }
88
+
89
+ .separator,
90
+ :global(.byline-draggable-menu-separator) {
91
+ width: 90%;
92
+ margin: 0.25rem auto;
93
+ border: none;
94
+ border-top: var(--border-width-thin) var(--border-style-solid) var(--gray-200);
95
+ }
96
+
97
+ /* ─── Dark theme variants ───────────────────────────────────── */
98
+
99
+ :is([data-theme="dark"], :global(.dark)) {
100
+ .menu,
101
+ :global(.byline-draggable-menu) {
102
+ background-color: var(--canvas-800);
103
+ border-color: var(--canvas-700);
104
+ }
105
+
106
+ .item,
107
+ :global(.byline-draggable-menu-item) {
108
+ color: var(--gray-300);
109
+ }
110
+
111
+ .item:hover,
112
+ .item:focus,
113
+ :global(.byline-draggable-menu-item):hover,
114
+ :global(.byline-draggable-menu-item):focus {
115
+ background-color: var(--canvas-900);
116
+ }
117
+
118
+ .label,
119
+ :global(.byline-draggable-menu-label) {
120
+ color: var(--gray-300);
121
+ }
122
+
123
+ .separator,
124
+ :global(.byline-draggable-menu-separator) {
125
+ border-top-color: var(--gray-900);
126
+ }
127
+ }
@@ -0,0 +1,85 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * This Source Code is subject to the terms of the Mozilla Public
5
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
+ *
8
+ * Copyright (c) Infonomic Company Limited
9
+ */
10
+
11
+ import {
12
+ DeleteIcon,
13
+ Dropdown as DropdownMenu,
14
+ EllipsisIcon,
15
+ IconButton,
16
+ PlusIcon,
17
+ } from '@infonomic/uikit/react'
18
+ import cx from 'classnames'
19
+
20
+ import styles from './draggable-context-menu.module.css'
21
+
22
+ interface DraggableContextMenuProps {
23
+ onAddBelow?: () => void
24
+ onRemove?: () => void
25
+ }
26
+
27
+ export function DraggableContextMenu({
28
+ onAddBelow,
29
+ onRemove,
30
+ }: DraggableContextMenuProps): React.JSX.Element {
31
+ const itemClass = cx('byline-draggable-menu-item', styles.item)
32
+ const rowClass = cx('byline-draggable-menu-row', styles.row)
33
+ const iconSlotClass = cx('byline-draggable-menu-icon-slot', styles['icon-slot'])
34
+ const labelClass = cx('byline-draggable-menu-label', styles.label)
35
+
36
+ return (
37
+ <DropdownMenu.Root modal={false}>
38
+ <DropdownMenu.Trigger render={<IconButton variant="text" size="sm" />}>
39
+ <EllipsisIcon width="16px" height="16px" />
40
+ </DropdownMenu.Trigger>
41
+
42
+ <DropdownMenu.Portal>
43
+ <DropdownMenu.Content
44
+ align="end"
45
+ sideOffset={0}
46
+ className={cx('byline-draggable-menu', styles.menu)}
47
+ >
48
+ <DropdownMenu.Item className={itemClass} onClick={onAddBelow}>
49
+ <div className={rowClass}>
50
+ <span className={iconSlotClass}>
51
+ <PlusIcon width="18px" height="18px" />
52
+ </span>
53
+ <span className={labelClass}>Add Below</span>
54
+ </div>
55
+ </DropdownMenu.Item>
56
+ <DropdownMenu.Separator
57
+ className={cx('byline-draggable-menu-separator', styles.separator)}
58
+ />
59
+ <DropdownMenu.Item className={itemClass} onClick={onRemove}>
60
+ <div className={rowClass}>
61
+ <div className={rowClass}>
62
+ <span className={iconSlotClass}>
63
+ <DeleteIcon
64
+ width="18px"
65
+ height="18px"
66
+ svgClassName={cx('byline-draggable-menu-delete-icon', styles['delete-icon'])}
67
+ />
68
+ </span>
69
+ <span
70
+ className={cx(
71
+ 'byline-draggable-menu-label byline-draggable-menu-label-danger',
72
+ styles.label,
73
+ styles['label-danger']
74
+ )}
75
+ >
76
+ Remove
77
+ </span>
78
+ </div>
79
+ </div>
80
+ </DropdownMenu.Item>
81
+ </DropdownMenu.Content>
82
+ </DropdownMenu.Portal>
83
+ </DropdownMenu.Root>
84
+ )
85
+ }