@multiplatform.one/frappe-ui 7.7.4 → 7.8.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 (670) hide show
  1. package/dist/cjs/ChartCard.native.js.map +1 -1
  2. package/dist/cjs/FileBrowser/AttachLibrary.native.js.map +1 -1
  3. package/dist/cjs/FileBrowser/folderTree.native.js.map +1 -1
  4. package/dist/cjs/FileBrowser/index.native.js.map +1 -1
  5. package/dist/cjs/FileBrowser/types.native.js.map +1 -1
  6. package/dist/cjs/FileBrowser/viewPersistence.native.js.map +1 -1
  7. package/dist/cjs/FormSidebar.native.js.map +1 -1
  8. package/dist/cjs/FrappeAssignment.cjs +1 -0
  9. package/dist/cjs/FrappeAssignment.native.js +1 -0
  10. package/dist/cjs/FrappeAssignment.native.js.map +1 -1
  11. package/dist/cjs/FrappeCalendar.cjs +22 -18
  12. package/dist/cjs/FrappeCalendar.native.js +24 -22
  13. package/dist/cjs/FrappeCalendar.native.js.map +1 -1
  14. package/dist/cjs/FrappeChartCard.cjs +1 -0
  15. package/dist/cjs/FrappeChartCard.native.js +1 -0
  16. package/dist/cjs/FrappeChartCard.native.js.map +1 -1
  17. package/dist/cjs/FrappeConnectionIndicator.native.js.map +1 -1
  18. package/dist/cjs/FrappeDashboard.cjs +1 -0
  19. package/dist/cjs/FrappeDashboard.native.js +1 -0
  20. package/dist/cjs/FrappeDashboard.native.js.map +1 -1
  21. package/dist/cjs/FrappeForm.cjs +3 -2
  22. package/dist/cjs/FrappeForm.native.js +4 -3
  23. package/dist/cjs/FrappeForm.native.js.map +1 -1
  24. package/dist/cjs/FrappeGantt.cjs +27 -35
  25. package/dist/cjs/FrappeGantt.native.js +29 -39
  26. package/dist/cjs/FrappeGantt.native.js.map +1 -1
  27. package/dist/cjs/FrappeImageView.cjs +6 -3
  28. package/dist/cjs/FrappeImageView.native.js +10 -5
  29. package/dist/cjs/FrappeImageView.native.js.map +1 -1
  30. package/dist/cjs/FrappeKPICard.cjs +27 -1
  31. package/dist/cjs/FrappeKPICard.native.js +27 -1
  32. package/dist/cjs/FrappeKPICard.native.js.map +1 -1
  33. package/dist/cjs/FrappeKanban.cjs +18 -18
  34. package/dist/cjs/FrappeKanban.native.js +20 -22
  35. package/dist/cjs/FrappeKanban.native.js.map +1 -1
  36. package/dist/cjs/FrappeLikedBy.cjs +2 -1
  37. package/dist/cjs/FrappeLikedBy.native.js +2 -1
  38. package/dist/cjs/FrappeLikedBy.native.js.map +1 -1
  39. package/dist/cjs/FrappeList.cjs +4 -3
  40. package/dist/cjs/FrappeList.native.js +4 -3
  41. package/dist/cjs/FrappeList.native.js.map +1 -1
  42. package/dist/cjs/FrappeListView.cjs +1 -0
  43. package/dist/cjs/FrappeListView.native.js +1 -0
  44. package/dist/cjs/FrappeListView.native.js.map +1 -1
  45. package/dist/cjs/FrappeProvider.cjs +3 -1
  46. package/dist/cjs/FrappeProvider.native.js +3 -1
  47. package/dist/cjs/FrappeProvider.native.js.map +1 -1
  48. package/dist/cjs/FrappeReconnectIndicator.native.js.map +1 -1
  49. package/dist/cjs/FrappeReportBuilder.cjs +3 -2
  50. package/dist/cjs/FrappeReportBuilder.native.js +3 -2
  51. package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
  52. package/dist/cjs/FrappeReportView.cjs +2 -1
  53. package/dist/cjs/FrappeReportView.native.js +5 -4
  54. package/dist/cjs/FrappeReportView.native.js.map +1 -1
  55. package/dist/cjs/FrappeTable.cjs +37 -39
  56. package/dist/cjs/FrappeTable.native.js +40 -40
  57. package/dist/cjs/FrappeTable.native.js.map +1 -1
  58. package/dist/cjs/FrappeTreeView.cjs +87 -51
  59. package/dist/cjs/FrappeTreeView.native.js +131 -51
  60. package/dist/cjs/FrappeTreeView.native.js.map +1 -1
  61. package/dist/cjs/SyncErrorNotice.native.js.map +1 -1
  62. package/dist/cjs/commentActions.cjs +1 -1
  63. package/dist/cjs/commentActions.native.js +1 -1
  64. package/dist/cjs/commentActions.native.js.map +1 -1
  65. package/dist/cjs/components/attachments.cjs +1 -0
  66. package/dist/cjs/components/attachments.native.js +1 -0
  67. package/dist/cjs/components/attachments.native.js.map +1 -1
  68. package/dist/cjs/components/tags.cjs +1 -0
  69. package/dist/cjs/components/tags.native.js +1 -0
  70. package/dist/cjs/components/tags.native.js.map +1 -1
  71. package/dist/cjs/components/timeline.cjs +2 -1
  72. package/dist/cjs/components/timeline.native.js +2 -1
  73. package/dist/cjs/components/timeline.native.js.map +1 -1
  74. package/dist/cjs/dependsOn.native.js.map +1 -1
  75. package/dist/cjs/desk/DeskFormPage.native.js.map +1 -1
  76. package/dist/cjs/desk/DeskFormSidebar.cjs +1 -0
  77. package/dist/cjs/desk/DeskFormSidebar.native.js +1 -0
  78. package/dist/cjs/desk/DeskFormSidebar.native.js.map +1 -1
  79. package/dist/cjs/desk/DeskListPage.native.js.map +1 -1
  80. package/dist/cjs/desk/DeskShell.cjs +2 -0
  81. package/dist/cjs/desk/DeskShell.native.js +2 -0
  82. package/dist/cjs/desk/DeskShell.native.js.map +1 -1
  83. package/dist/cjs/desk/DeskSidebar.cjs +1 -0
  84. package/dist/cjs/desk/DeskSidebar.native.js +1 -0
  85. package/dist/cjs/desk/DeskSidebar.native.js.map +1 -1
  86. package/dist/cjs/desk/awesomebar.cjs +2 -1
  87. package/dist/cjs/desk/awesomebar.native.js +2 -1
  88. package/dist/cjs/desk/awesomebar.native.js.map +1 -1
  89. package/dist/cjs/fieldOverrides.native.js.map +1 -1
  90. package/dist/cjs/fieldRegistry.cjs +1 -0
  91. package/dist/cjs/fieldRegistry.native.js +32 -31
  92. package/dist/cjs/fieldRegistry.native.js.map +1 -1
  93. package/dist/cjs/fields/Barcode/index.native.js.map +1 -1
  94. package/dist/cjs/fields/Check/index.native.js.map +1 -1
  95. package/dist/cjs/fields/CodeEditor/index.native.js.map +1 -1
  96. package/dist/cjs/fields/Color/index.native.js.map +1 -1
  97. package/dist/cjs/fields/Data/index.native.js.map +1 -1
  98. package/dist/cjs/fields/Date/sheetKeyboard.native.js.map +1 -1
  99. package/dist/cjs/fields/Date/types.native.js.map +1 -1
  100. package/dist/cjs/fields/Date/wire.native.js.map +1 -1
  101. package/dist/cjs/fields/DateRange/index.native.js.map +1 -1
  102. package/dist/cjs/fields/Duration/index.native.js.map +1 -1
  103. package/dist/cjs/fields/DynamicLink.native.js.map +1 -1
  104. package/dist/cjs/fields/FileUpload.cjs +1 -0
  105. package/dist/cjs/fields/FileUpload.native.js +1 -0
  106. package/dist/cjs/fields/FileUpload.native.js.map +1 -1
  107. package/dist/cjs/fields/FileUploadField/index.native.js.map +1 -1
  108. package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
  109. package/dist/cjs/fields/HTML/index.native.js.map +1 -1
  110. package/dist/cjs/fields/Heading/index.native.js.map +1 -1
  111. package/dist/cjs/fields/Icon/index.native.js.map +1 -1
  112. package/dist/cjs/fields/Link.cjs +1 -0
  113. package/dist/cjs/fields/Link.native.js +1 -0
  114. package/dist/cjs/fields/Link.native.js.map +1 -1
  115. package/dist/cjs/fields/LinkTree.cjs +2 -1
  116. package/dist/cjs/fields/LinkTree.native.js +2 -1
  117. package/dist/cjs/fields/LinkTree.native.js.map +1 -1
  118. package/dist/cjs/fields/LongText/index.native.js.map +1 -1
  119. package/dist/cjs/fields/MentionInput/index.cjs +4 -1
  120. package/dist/cjs/fields/MentionInput/index.native.js +4 -1
  121. package/dist/cjs/fields/MentionInput/index.native.js.map +1 -1
  122. package/dist/cjs/fields/Numeric/index.native.js.map +1 -1
  123. package/dist/cjs/fields/OTPInput/index.native.js.map +1 -1
  124. package/dist/cjs/fields/Password/index.native.js.map +1 -1
  125. package/dist/cjs/fields/Phone/index.native.js.map +1 -1
  126. package/dist/cjs/fields/Progress/index.native.js.map +1 -1
  127. package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
  128. package/dist/cjs/fields/Rating/index.native.js.map +1 -1
  129. package/dist/cjs/fields/ReadOnly/index.native.js.map +1 -1
  130. package/dist/cjs/fields/Select/index.native.js.map +1 -1
  131. package/dist/cjs/fields/Signature/index.native.js.map +1 -1
  132. package/dist/cjs/fields/Slider/index.native.js.map +1 -1
  133. package/dist/cjs/fields/SmallText/index.native.js.map +1 -1
  134. package/dist/cjs/fields/Switch/index.native.js.map +1 -1
  135. package/dist/cjs/fields/TableMultiSelect.cjs +1 -0
  136. package/dist/cjs/fields/TableMultiSelect.native.js +1 -0
  137. package/dist/cjs/fields/TableMultiSelect.native.js.map +1 -1
  138. package/dist/cjs/fields/TextEditor/types.native.js.map +1 -1
  139. package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
  140. package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
  141. package/dist/cjs/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  142. package/dist/cjs/filterFields.native.js.map +1 -1
  143. package/dist/cjs/formEngine/createPrefill.native.js.map +1 -1
  144. package/dist/cjs/formEngine/dirtyTracking.native.js.map +1 -1
  145. package/dist/cjs/formEngine/doctypeMeta.native.js.map +1 -1
  146. package/dist/cjs/formEngine/fetchFrom.native.js.map +1 -1
  147. package/dist/cjs/formEngine/fieldPermissions.native.js.map +1 -1
  148. package/dist/cjs/formEngine/formActions.native.js.map +1 -1
  149. package/dist/cjs/formEngine/formLayout.native.js.map +1 -1
  150. package/dist/cjs/formEngine/index.native.js.map +1 -1
  151. package/dist/cjs/formEngine/useFormEngine.native.js.map +1 -1
  152. package/dist/cjs/frappeEventColor.native.js.map +1 -1
  153. package/dist/cjs/frappeStoryTarget.native.js.map +1 -1
  154. package/dist/cjs/frappeUsers.cjs +1 -0
  155. package/dist/cjs/frappeUsers.native.js +1 -0
  156. package/dist/cjs/frappeUsers.native.js.map +1 -1
  157. package/dist/cjs/index.cjs +4 -0
  158. package/dist/cjs/index.native.js +38 -34
  159. package/dist/cjs/index.native.js.map +1 -1
  160. package/dist/cjs/liveErrors.native.js.map +1 -1
  161. package/dist/cjs/resolveControl.native.js.map +1 -1
  162. package/dist/cjs/schemaForm/SchemaWizard.native.js.map +1 -1
  163. package/dist/cjs/schemaForm/applyFieldOrder.native.js.map +1 -1
  164. package/dist/cjs/schemaForm/index.cjs +10 -9
  165. package/dist/cjs/schemaForm/index.native.js +11 -10
  166. package/dist/cjs/schemaForm/index.native.js.map +1 -1
  167. package/dist/cjs/shared/devWarn.cjs +40 -0
  168. package/dist/cjs/shared/devWarn.native.js +45 -0
  169. package/dist/cjs/shared/devWarn.native.js.map +1 -0
  170. package/dist/cjs/shared/useKeyboardInset.native.js.map +1 -1
  171. package/dist/cjs/syncError.native.js.map +1 -1
  172. package/dist/cjs/useFrappeAggregate.cjs +15 -8
  173. package/dist/cjs/useFrappeAggregate.native.js +15 -9
  174. package/dist/cjs/useFrappeAggregate.native.js.map +1 -1
  175. package/dist/cjs/useFrappeFacets.cjs +10 -9
  176. package/dist/cjs/useFrappeFacets.native.js +10 -10
  177. package/dist/cjs/useFrappeFacets.native.js.map +1 -1
  178. package/dist/cjs/useFrappePagination.native.js.map +1 -1
  179. package/dist/cjs/useFrappeRows.cjs +113 -0
  180. package/dist/cjs/useFrappeRows.native.js +129 -0
  181. package/dist/cjs/useFrappeRows.native.js.map +1 -0
  182. package/dist/esm/ChartCard.native.js.map +1 -1
  183. package/dist/esm/FileBrowser/AttachLibrary.native.js.map +1 -1
  184. package/dist/esm/FileBrowser/folderTree.native.js.map +1 -1
  185. package/dist/esm/FileBrowser/index.native.js.map +1 -1
  186. package/dist/esm/FileBrowser/types.native.js.map +1 -1
  187. package/dist/esm/FileBrowser/viewPersistence.native.js.map +1 -1
  188. package/dist/esm/FormSidebar.native.js.map +1 -1
  189. package/dist/esm/FrappeAssignment.mjs +1 -0
  190. package/dist/esm/FrappeAssignment.mjs.map +1 -1
  191. package/dist/esm/FrappeAssignment.native.js +1 -0
  192. package/dist/esm/FrappeAssignment.native.js.map +1 -1
  193. package/dist/esm/FrappeCalendar.mjs +22 -18
  194. package/dist/esm/FrappeCalendar.mjs.map +1 -1
  195. package/dist/esm/FrappeCalendar.native.js +24 -22
  196. package/dist/esm/FrappeCalendar.native.js.map +1 -1
  197. package/dist/esm/FrappeChartCard.mjs +1 -0
  198. package/dist/esm/FrappeChartCard.mjs.map +1 -1
  199. package/dist/esm/FrappeChartCard.native.js +1 -0
  200. package/dist/esm/FrappeChartCard.native.js.map +1 -1
  201. package/dist/esm/FrappeConnectionIndicator.native.js.map +1 -1
  202. package/dist/esm/FrappeDashboard.mjs +1 -0
  203. package/dist/esm/FrappeDashboard.mjs.map +1 -1
  204. package/dist/esm/FrappeDashboard.native.js +1 -0
  205. package/dist/esm/FrappeDashboard.native.js.map +1 -1
  206. package/dist/esm/FrappeForm.mjs +3 -2
  207. package/dist/esm/FrappeForm.mjs.map +1 -1
  208. package/dist/esm/FrappeForm.native.js +3 -2
  209. package/dist/esm/FrappeForm.native.js.map +1 -1
  210. package/dist/esm/FrappeGantt.mjs +29 -37
  211. package/dist/esm/FrappeGantt.mjs.map +1 -1
  212. package/dist/esm/FrappeGantt.native.js +31 -41
  213. package/dist/esm/FrappeGantt.native.js.map +1 -1
  214. package/dist/esm/FrappeImageView.mjs +7 -4
  215. package/dist/esm/FrappeImageView.mjs.map +1 -1
  216. package/dist/esm/FrappeImageView.native.js +11 -6
  217. package/dist/esm/FrappeImageView.native.js.map +1 -1
  218. package/dist/esm/FrappeKPICard.mjs +28 -2
  219. package/dist/esm/FrappeKPICard.mjs.map +1 -1
  220. package/dist/esm/FrappeKPICard.native.js +28 -2
  221. package/dist/esm/FrappeKPICard.native.js.map +1 -1
  222. package/dist/esm/FrappeKanban.mjs +18 -18
  223. package/dist/esm/FrappeKanban.mjs.map +1 -1
  224. package/dist/esm/FrappeKanban.native.js +20 -22
  225. package/dist/esm/FrappeKanban.native.js.map +1 -1
  226. package/dist/esm/FrappeLikedBy.mjs +2 -1
  227. package/dist/esm/FrappeLikedBy.mjs.map +1 -1
  228. package/dist/esm/FrappeLikedBy.native.js +2 -1
  229. package/dist/esm/FrappeLikedBy.native.js.map +1 -1
  230. package/dist/esm/FrappeList.mjs +4 -3
  231. package/dist/esm/FrappeList.mjs.map +1 -1
  232. package/dist/esm/FrappeList.native.js +4 -3
  233. package/dist/esm/FrappeList.native.js.map +1 -1
  234. package/dist/esm/FrappeListView.mjs +1 -0
  235. package/dist/esm/FrappeListView.mjs.map +1 -1
  236. package/dist/esm/FrappeListView.native.js +1 -0
  237. package/dist/esm/FrappeListView.native.js.map +1 -1
  238. package/dist/esm/FrappeProvider.mjs +3 -1
  239. package/dist/esm/FrappeProvider.mjs.map +1 -1
  240. package/dist/esm/FrappeProvider.native.js +3 -1
  241. package/dist/esm/FrappeProvider.native.js.map +1 -1
  242. package/dist/esm/FrappeReconnectIndicator.native.js.map +1 -1
  243. package/dist/esm/FrappeReportBuilder.mjs +3 -2
  244. package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
  245. package/dist/esm/FrappeReportBuilder.native.js +3 -2
  246. package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
  247. package/dist/esm/FrappeReportView.mjs +2 -1
  248. package/dist/esm/FrappeReportView.mjs.map +1 -1
  249. package/dist/esm/FrappeReportView.native.js +2 -1
  250. package/dist/esm/FrappeReportView.native.js.map +1 -1
  251. package/dist/esm/FrappeTable.mjs +38 -40
  252. package/dist/esm/FrappeTable.mjs.map +1 -1
  253. package/dist/esm/FrappeTable.native.js +41 -41
  254. package/dist/esm/FrappeTable.native.js.map +1 -1
  255. package/dist/esm/FrappeTreeView.mjs +91 -56
  256. package/dist/esm/FrappeTreeView.mjs.map +1 -1
  257. package/dist/esm/FrappeTreeView.native.js +135 -56
  258. package/dist/esm/FrappeTreeView.native.js.map +1 -1
  259. package/dist/esm/SyncErrorNotice.native.js.map +1 -1
  260. package/dist/esm/commentActions.mjs +1 -1
  261. package/dist/esm/commentActions.mjs.map +1 -1
  262. package/dist/esm/commentActions.native.js +1 -1
  263. package/dist/esm/commentActions.native.js.map +1 -1
  264. package/dist/esm/components/attachments.mjs +1 -0
  265. package/dist/esm/components/attachments.mjs.map +1 -1
  266. package/dist/esm/components/attachments.native.js +1 -0
  267. package/dist/esm/components/attachments.native.js.map +1 -1
  268. package/dist/esm/components/tags.mjs +1 -0
  269. package/dist/esm/components/tags.mjs.map +1 -1
  270. package/dist/esm/components/tags.native.js +1 -0
  271. package/dist/esm/components/tags.native.js.map +1 -1
  272. package/dist/esm/components/timeline.mjs +2 -1
  273. package/dist/esm/components/timeline.mjs.map +1 -1
  274. package/dist/esm/components/timeline.native.js +2 -1
  275. package/dist/esm/components/timeline.native.js.map +1 -1
  276. package/dist/esm/dependsOn.native.js.map +1 -1
  277. package/dist/esm/desk/DeskFormPage.native.js.map +1 -1
  278. package/dist/esm/desk/DeskFormSidebar.mjs +1 -0
  279. package/dist/esm/desk/DeskFormSidebar.mjs.map +1 -1
  280. package/dist/esm/desk/DeskFormSidebar.native.js +1 -0
  281. package/dist/esm/desk/DeskFormSidebar.native.js.map +1 -1
  282. package/dist/esm/desk/DeskListPage.native.js.map +1 -1
  283. package/dist/esm/desk/DeskShell.mjs +2 -0
  284. package/dist/esm/desk/DeskShell.mjs.map +1 -1
  285. package/dist/esm/desk/DeskShell.native.js +2 -0
  286. package/dist/esm/desk/DeskShell.native.js.map +1 -1
  287. package/dist/esm/desk/DeskSidebar.mjs +1 -0
  288. package/dist/esm/desk/DeskSidebar.mjs.map +1 -1
  289. package/dist/esm/desk/DeskSidebar.native.js +1 -0
  290. package/dist/esm/desk/DeskSidebar.native.js.map +1 -1
  291. package/dist/esm/desk/awesomebar.mjs +2 -1
  292. package/dist/esm/desk/awesomebar.mjs.map +1 -1
  293. package/dist/esm/desk/awesomebar.native.js +2 -1
  294. package/dist/esm/desk/awesomebar.native.js.map +1 -1
  295. package/dist/esm/fieldOverrides.native.js.map +1 -1
  296. package/dist/esm/fieldRegistry.mjs +1 -0
  297. package/dist/esm/fieldRegistry.mjs.map +1 -1
  298. package/dist/esm/fieldRegistry.native.js +1 -0
  299. package/dist/esm/fieldRegistry.native.js.map +1 -1
  300. package/dist/esm/fields/Barcode/index.native.js.map +1 -1
  301. package/dist/esm/fields/Check/index.native.js.map +1 -1
  302. package/dist/esm/fields/CodeEditor/index.native.js.map +1 -1
  303. package/dist/esm/fields/Color/index.native.js.map +1 -1
  304. package/dist/esm/fields/Data/index.native.js.map +1 -1
  305. package/dist/esm/fields/Date/sheetKeyboard.native.js.map +1 -1
  306. package/dist/esm/fields/Date/types.native.js.map +1 -1
  307. package/dist/esm/fields/Date/wire.native.js.map +1 -1
  308. package/dist/esm/fields/DateRange/index.native.js.map +1 -1
  309. package/dist/esm/fields/Duration/index.native.js.map +1 -1
  310. package/dist/esm/fields/DynamicLink.native.js.map +1 -1
  311. package/dist/esm/fields/FileUpload.mjs +1 -0
  312. package/dist/esm/fields/FileUpload.mjs.map +1 -1
  313. package/dist/esm/fields/FileUpload.native.js +1 -0
  314. package/dist/esm/fields/FileUpload.native.js.map +1 -1
  315. package/dist/esm/fields/FileUploadField/index.native.js.map +1 -1
  316. package/dist/esm/fields/Geolocation/index.native.js.map +1 -1
  317. package/dist/esm/fields/HTML/index.native.js.map +1 -1
  318. package/dist/esm/fields/Heading/index.native.js.map +1 -1
  319. package/dist/esm/fields/Icon/index.native.js.map +1 -1
  320. package/dist/esm/fields/Link.mjs +1 -0
  321. package/dist/esm/fields/Link.mjs.map +1 -1
  322. package/dist/esm/fields/Link.native.js +1 -0
  323. package/dist/esm/fields/Link.native.js.map +1 -1
  324. package/dist/esm/fields/LinkTree.mjs +2 -1
  325. package/dist/esm/fields/LinkTree.mjs.map +1 -1
  326. package/dist/esm/fields/LinkTree.native.js +2 -1
  327. package/dist/esm/fields/LinkTree.native.js.map +1 -1
  328. package/dist/esm/fields/LongText/index.native.js.map +1 -1
  329. package/dist/esm/fields/MentionInput/index.mjs +4 -1
  330. package/dist/esm/fields/MentionInput/index.mjs.map +1 -1
  331. package/dist/esm/fields/MentionInput/index.native.js +4 -1
  332. package/dist/esm/fields/MentionInput/index.native.js.map +1 -1
  333. package/dist/esm/fields/Numeric/index.native.js.map +1 -1
  334. package/dist/esm/fields/OTPInput/index.native.js.map +1 -1
  335. package/dist/esm/fields/Password/index.native.js.map +1 -1
  336. package/dist/esm/fields/Phone/index.native.js.map +1 -1
  337. package/dist/esm/fields/Progress/index.native.js.map +1 -1
  338. package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
  339. package/dist/esm/fields/Rating/index.native.js.map +1 -1
  340. package/dist/esm/fields/ReadOnly/index.native.js.map +1 -1
  341. package/dist/esm/fields/Select/index.native.js.map +1 -1
  342. package/dist/esm/fields/Signature/index.native.js.map +1 -1
  343. package/dist/esm/fields/Slider/index.native.js.map +1 -1
  344. package/dist/esm/fields/SmallText/index.native.js.map +1 -1
  345. package/dist/esm/fields/Switch/index.native.js.map +1 -1
  346. package/dist/esm/fields/TableMultiSelect.mjs +1 -0
  347. package/dist/esm/fields/TableMultiSelect.mjs.map +1 -1
  348. package/dist/esm/fields/TableMultiSelect.native.js +1 -0
  349. package/dist/esm/fields/TableMultiSelect.native.js.map +1 -1
  350. package/dist/esm/fields/TextEditor/types.native.js.map +1 -1
  351. package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
  352. package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
  353. package/dist/esm/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  354. package/dist/esm/filterFields.native.js.map +1 -1
  355. package/dist/esm/formEngine/createPrefill.native.js.map +1 -1
  356. package/dist/esm/formEngine/dirtyTracking.native.js.map +1 -1
  357. package/dist/esm/formEngine/doctypeMeta.native.js.map +1 -1
  358. package/dist/esm/formEngine/fetchFrom.native.js.map +1 -1
  359. package/dist/esm/formEngine/fieldPermissions.native.js.map +1 -1
  360. package/dist/esm/formEngine/formActions.mjs.map +1 -1
  361. package/dist/esm/formEngine/formActions.native.js.map +1 -1
  362. package/dist/esm/formEngine/formLayout.native.js.map +1 -1
  363. package/dist/esm/formEngine/index.native.js.map +1 -1
  364. package/dist/esm/formEngine/useFormEngine.native.js.map +1 -1
  365. package/dist/esm/frappeEventColor.native.js.map +1 -1
  366. package/dist/esm/frappeStoryTarget.native.js.map +1 -1
  367. package/dist/esm/frappeUsers.mjs +1 -0
  368. package/dist/esm/frappeUsers.mjs.map +1 -1
  369. package/dist/esm/frappeUsers.native.js +1 -0
  370. package/dist/esm/frappeUsers.native.js.map +1 -1
  371. package/dist/esm/index.mjs +2 -1
  372. package/dist/esm/index.mjs.map +1 -1
  373. package/dist/esm/index.native.js +2 -1
  374. package/dist/esm/index.native.js.map +1 -1
  375. package/dist/esm/liveErrors.native.js.map +1 -1
  376. package/dist/esm/resolveControl.native.js.map +1 -1
  377. package/dist/esm/schemaForm/SchemaWizard.native.js.map +1 -1
  378. package/dist/esm/schemaForm/applyFieldOrder.native.js.map +1 -1
  379. package/dist/esm/schemaForm/index.mjs +8 -7
  380. package/dist/esm/schemaForm/index.mjs.map +1 -1
  381. package/dist/esm/schemaForm/index.native.js +8 -7
  382. package/dist/esm/schemaForm/index.native.js.map +1 -1
  383. package/dist/esm/shared/devWarn.mjs +14 -0
  384. package/dist/esm/shared/devWarn.mjs.map +1 -0
  385. package/dist/esm/shared/devWarn.native.js +16 -0
  386. package/dist/esm/shared/devWarn.native.js.map +1 -0
  387. package/dist/esm/shared/useKeyboardInset.native.js.map +1 -1
  388. package/dist/esm/syncError.native.js.map +1 -1
  389. package/dist/esm/useFrappeAggregate.mjs +15 -8
  390. package/dist/esm/useFrappeAggregate.mjs.map +1 -1
  391. package/dist/esm/useFrappeAggregate.native.js +15 -9
  392. package/dist/esm/useFrappeAggregate.native.js.map +1 -1
  393. package/dist/esm/useFrappeFacets.mjs +10 -9
  394. package/dist/esm/useFrappeFacets.mjs.map +1 -1
  395. package/dist/esm/useFrappeFacets.native.js +10 -10
  396. package/dist/esm/useFrappeFacets.native.js.map +1 -1
  397. package/dist/esm/useFrappePagination.native.js.map +1 -1
  398. package/dist/esm/useFrappeRows.mjs +86 -0
  399. package/dist/esm/useFrappeRows.mjs.map +1 -0
  400. package/dist/esm/useFrappeRows.native.js +99 -0
  401. package/dist/esm/useFrappeRows.native.js.map +1 -0
  402. package/dist/jsx/FrappeAssignment.mjs +1 -0
  403. package/dist/jsx/FrappeAssignment.mjs.map +1 -1
  404. package/dist/jsx/FrappeAssignment.native.js +1 -0
  405. package/dist/jsx/FrappeAssignment.native.js.map +1 -1
  406. package/dist/jsx/FrappeCalendar.mjs +22 -18
  407. package/dist/jsx/FrappeCalendar.mjs.map +1 -1
  408. package/dist/jsx/FrappeCalendar.native.js +24 -22
  409. package/dist/jsx/FrappeCalendar.native.js.map +1 -1
  410. package/dist/jsx/FrappeChartCard.mjs +1 -0
  411. package/dist/jsx/FrappeChartCard.mjs.map +1 -1
  412. package/dist/jsx/FrappeChartCard.native.js +1 -0
  413. package/dist/jsx/FrappeChartCard.native.js.map +1 -1
  414. package/dist/jsx/FrappeDashboard.mjs +1 -0
  415. package/dist/jsx/FrappeDashboard.mjs.map +1 -1
  416. package/dist/jsx/FrappeDashboard.native.js +1 -0
  417. package/dist/jsx/FrappeDashboard.native.js.map +1 -1
  418. package/dist/jsx/FrappeForm.mjs +3 -2
  419. package/dist/jsx/FrappeForm.mjs.map +1 -1
  420. package/dist/jsx/FrappeForm.native.js +3 -2
  421. package/dist/jsx/FrappeForm.native.js.map +1 -1
  422. package/dist/jsx/FrappeGantt.mjs +29 -37
  423. package/dist/jsx/FrappeGantt.mjs.map +1 -1
  424. package/dist/jsx/FrappeGantt.native.js +29 -39
  425. package/dist/jsx/FrappeGantt.native.js.map +1 -1
  426. package/dist/jsx/FrappeImageView.mjs +7 -4
  427. package/dist/jsx/FrappeImageView.mjs.map +1 -1
  428. package/dist/jsx/FrappeImageView.native.js +10 -5
  429. package/dist/jsx/FrappeImageView.native.js.map +1 -1
  430. package/dist/jsx/FrappeKPICard.mjs +28 -2
  431. package/dist/jsx/FrappeKPICard.mjs.map +1 -1
  432. package/dist/jsx/FrappeKPICard.native.js +27 -1
  433. package/dist/jsx/FrappeKPICard.native.js.map +1 -1
  434. package/dist/jsx/FrappeKanban.mjs +18 -18
  435. package/dist/jsx/FrappeKanban.mjs.map +1 -1
  436. package/dist/jsx/FrappeKanban.native.js +20 -22
  437. package/dist/jsx/FrappeKanban.native.js.map +1 -1
  438. package/dist/jsx/FrappeLikedBy.mjs +2 -1
  439. package/dist/jsx/FrappeLikedBy.mjs.map +1 -1
  440. package/dist/jsx/FrappeLikedBy.native.js +2 -1
  441. package/dist/jsx/FrappeLikedBy.native.js.map +1 -1
  442. package/dist/jsx/FrappeList.mjs +4 -3
  443. package/dist/jsx/FrappeList.mjs.map +1 -1
  444. package/dist/jsx/FrappeList.native.js +4 -3
  445. package/dist/jsx/FrappeList.native.js.map +1 -1
  446. package/dist/jsx/FrappeListView.mjs +1 -0
  447. package/dist/jsx/FrappeListView.mjs.map +1 -1
  448. package/dist/jsx/FrappeListView.native.js +1 -0
  449. package/dist/jsx/FrappeListView.native.js.map +1 -1
  450. package/dist/jsx/FrappeProvider.mjs +3 -1
  451. package/dist/jsx/FrappeProvider.mjs.map +1 -1
  452. package/dist/jsx/FrappeProvider.native.js +3 -1
  453. package/dist/jsx/FrappeProvider.native.js.map +1 -1
  454. package/dist/jsx/FrappeReportBuilder.mjs +3 -2
  455. package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
  456. package/dist/jsx/FrappeReportBuilder.native.js +3 -2
  457. package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
  458. package/dist/jsx/FrappeReportView.mjs +2 -1
  459. package/dist/jsx/FrappeReportView.mjs.map +1 -1
  460. package/dist/jsx/FrappeReportView.native.js +2 -1
  461. package/dist/jsx/FrappeReportView.native.js.map +1 -1
  462. package/dist/jsx/FrappeTable.mjs +38 -40
  463. package/dist/jsx/FrappeTable.mjs.map +1 -1
  464. package/dist/jsx/FrappeTable.native.js +40 -40
  465. package/dist/jsx/FrappeTable.native.js.map +1 -1
  466. package/dist/jsx/FrappeTreeView.mjs +91 -56
  467. package/dist/jsx/FrappeTreeView.mjs.map +1 -1
  468. package/dist/jsx/FrappeTreeView.native.js +131 -51
  469. package/dist/jsx/FrappeTreeView.native.js.map +1 -1
  470. package/dist/jsx/commentActions.mjs +1 -1
  471. package/dist/jsx/commentActions.mjs.map +1 -1
  472. package/dist/jsx/commentActions.native.js +1 -1
  473. package/dist/jsx/commentActions.native.js.map +1 -1
  474. package/dist/jsx/components/attachments.mjs +1 -0
  475. package/dist/jsx/components/attachments.mjs.map +1 -1
  476. package/dist/jsx/components/attachments.native.js +1 -0
  477. package/dist/jsx/components/attachments.native.js.map +1 -1
  478. package/dist/jsx/components/tags.mjs +1 -0
  479. package/dist/jsx/components/tags.mjs.map +1 -1
  480. package/dist/jsx/components/tags.native.js +1 -0
  481. package/dist/jsx/components/tags.native.js.map +1 -1
  482. package/dist/jsx/components/timeline.mjs +2 -1
  483. package/dist/jsx/components/timeline.mjs.map +1 -1
  484. package/dist/jsx/components/timeline.native.js +2 -1
  485. package/dist/jsx/components/timeline.native.js.map +1 -1
  486. package/dist/jsx/desk/DeskFormSidebar.mjs +1 -0
  487. package/dist/jsx/desk/DeskFormSidebar.mjs.map +1 -1
  488. package/dist/jsx/desk/DeskFormSidebar.native.js +1 -0
  489. package/dist/jsx/desk/DeskFormSidebar.native.js.map +1 -1
  490. package/dist/jsx/desk/DeskShell.mjs +2 -0
  491. package/dist/jsx/desk/DeskShell.mjs.map +1 -1
  492. package/dist/jsx/desk/DeskShell.native.js +2 -0
  493. package/dist/jsx/desk/DeskShell.native.js.map +1 -1
  494. package/dist/jsx/desk/DeskSidebar.mjs +1 -0
  495. package/dist/jsx/desk/DeskSidebar.mjs.map +1 -1
  496. package/dist/jsx/desk/DeskSidebar.native.js +1 -0
  497. package/dist/jsx/desk/DeskSidebar.native.js.map +1 -1
  498. package/dist/jsx/desk/awesomebar.mjs +2 -1
  499. package/dist/jsx/desk/awesomebar.mjs.map +1 -1
  500. package/dist/jsx/desk/awesomebar.native.js +2 -1
  501. package/dist/jsx/desk/awesomebar.native.js.map +1 -1
  502. package/dist/jsx/fieldRegistry.mjs +1 -0
  503. package/dist/jsx/fieldRegistry.mjs.map +1 -1
  504. package/dist/jsx/fieldRegistry.native.js +1 -0
  505. package/dist/jsx/fieldRegistry.native.js.map +1 -1
  506. package/dist/jsx/fields/FileUpload.mjs +1 -0
  507. package/dist/jsx/fields/FileUpload.mjs.map +1 -1
  508. package/dist/jsx/fields/FileUpload.native.js +1 -0
  509. package/dist/jsx/fields/FileUpload.native.js.map +1 -1
  510. package/dist/jsx/fields/Link.mjs +1 -0
  511. package/dist/jsx/fields/Link.mjs.map +1 -1
  512. package/dist/jsx/fields/Link.native.js +1 -0
  513. package/dist/jsx/fields/Link.native.js.map +1 -1
  514. package/dist/jsx/fields/LinkTree.mjs +2 -1
  515. package/dist/jsx/fields/LinkTree.mjs.map +1 -1
  516. package/dist/jsx/fields/LinkTree.native.js +2 -1
  517. package/dist/jsx/fields/LinkTree.native.js.map +1 -1
  518. package/dist/jsx/fields/MentionInput/index.mjs +4 -1
  519. package/dist/jsx/fields/MentionInput/index.mjs.map +1 -1
  520. package/dist/jsx/fields/MentionInput/index.native.js +4 -1
  521. package/dist/jsx/fields/MentionInput/index.native.js.map +1 -1
  522. package/dist/jsx/fields/TableMultiSelect.mjs +1 -0
  523. package/dist/jsx/fields/TableMultiSelect.mjs.map +1 -1
  524. package/dist/jsx/fields/TableMultiSelect.native.js +1 -0
  525. package/dist/jsx/fields/TableMultiSelect.native.js.map +1 -1
  526. package/dist/jsx/formEngine/formActions.mjs.map +1 -1
  527. package/dist/jsx/formEngine/formActions.native.js.map +1 -1
  528. package/dist/jsx/frappeUsers.mjs +1 -0
  529. package/dist/jsx/frappeUsers.mjs.map +1 -1
  530. package/dist/jsx/frappeUsers.native.js +1 -0
  531. package/dist/jsx/frappeUsers.native.js.map +1 -1
  532. package/dist/jsx/index.js +2 -1
  533. package/dist/jsx/index.js.map +1 -1
  534. package/dist/jsx/index.mjs +2 -1
  535. package/dist/jsx/index.mjs.map +1 -1
  536. package/dist/jsx/index.native.js +4 -0
  537. package/dist/jsx/index.native.js.map +1 -1
  538. package/dist/jsx/schemaForm/index.mjs +8 -7
  539. package/dist/jsx/schemaForm/index.mjs.map +1 -1
  540. package/dist/jsx/schemaForm/index.native.js +10 -9
  541. package/dist/jsx/schemaForm/index.native.js.map +1 -1
  542. package/dist/jsx/shared/devWarn.mjs +14 -0
  543. package/dist/jsx/shared/devWarn.mjs.map +1 -0
  544. package/dist/jsx/shared/devWarn.native.js +45 -0
  545. package/dist/jsx/shared/devWarn.native.js.map +1 -0
  546. package/dist/jsx/useFrappeAggregate.mjs +15 -8
  547. package/dist/jsx/useFrappeAggregate.mjs.map +1 -1
  548. package/dist/jsx/useFrappeAggregate.native.js +15 -9
  549. package/dist/jsx/useFrappeAggregate.native.js.map +1 -1
  550. package/dist/jsx/useFrappeFacets.mjs +10 -9
  551. package/dist/jsx/useFrappeFacets.mjs.map +1 -1
  552. package/dist/jsx/useFrappeFacets.native.js +10 -10
  553. package/dist/jsx/useFrappeFacets.native.js.map +1 -1
  554. package/dist/jsx/useFrappeRows.mjs +86 -0
  555. package/dist/jsx/useFrappeRows.mjs.map +1 -0
  556. package/dist/jsx/useFrappeRows.native.js +129 -0
  557. package/dist/jsx/useFrappeRows.native.js.map +1 -0
  558. package/package.json +17 -16
  559. package/src/FileBrowser/FileBrowser.spec.tsx +11 -1
  560. package/src/FrappeAssignment.tsx +1 -0
  561. package/src/FrappeCalendar.tsx +27 -22
  562. package/src/FrappeChartCard.tsx +1 -0
  563. package/src/FrappeDashboard.tsx +3 -0
  564. package/src/FrappeForm.tsx +9 -3
  565. package/src/FrappeGantt.tsx +31 -39
  566. package/src/FrappeImageView.tsx +7 -3
  567. package/src/FrappeKPICard.spec.tsx +128 -0
  568. package/src/FrappeKPICard.tsx +45 -4
  569. package/src/FrappeKanban.tsx +26 -17
  570. package/src/FrappeLikedBy.tsx +2 -1
  571. package/src/FrappeList.tsx +5 -2
  572. package/src/FrappeListView.tsx +1 -0
  573. package/src/FrappeProvider.fixturesOnly.spec.tsx +129 -0
  574. package/src/FrappeProvider.realtime.spec.tsx +59 -0
  575. package/src/FrappeProvider.tsx +33 -7
  576. package/src/FrappeReportBuilder.tsx +5 -2
  577. package/src/FrappeReportView.tsx +5 -2
  578. package/src/FrappeTable.autoHeight.spec.tsx +142 -0
  579. package/src/FrappeTable.rowAccumulator.spec.tsx +110 -0
  580. package/src/FrappeTable.tsx +77 -48
  581. package/src/FrappeTreeView.stories.tsx +59 -0
  582. package/src/FrappeTreeView.tsx +168 -56
  583. package/src/commentActions.ts +1 -1
  584. package/src/components/attachments.tsx +1 -0
  585. package/src/components/tags.tsx +1 -0
  586. package/src/components/timeline.tsx +2 -1
  587. package/src/desk/DeskFormSidebar.tsx +1 -0
  588. package/src/desk/DeskShell.tsx +2 -0
  589. package/src/desk/DeskSidebar.tsx +6 -1
  590. package/src/desk/awesomebar.tsx +11 -3
  591. package/src/fieldRegistry.ts +1 -0
  592. package/src/fields/CodeEditor/CodeEditor.spec.tsx +10 -9
  593. package/src/fields/Date/typeParity.spec.tsx +19 -9
  594. package/src/fields/Duration/Duration.spec.tsx +73 -0
  595. package/src/fields/FileUpload.tsx +1 -0
  596. package/src/fields/Link.tsx +6 -1
  597. package/src/fields/LinkTree.tsx +2 -1
  598. package/src/fields/MentionInput/MentionInput.spec.tsx +110 -0
  599. package/src/fields/MentionInput/index.tsx +4 -1
  600. package/src/fields/Password/index.tsx +1 -1
  601. package/src/fields/Progress/Progress.spec.tsx +9 -0
  602. package/src/fields/RadioGroup/RadioGroup.spec.tsx +93 -0
  603. package/src/fields/Signature/Signature.spec.tsx +105 -0
  604. package/src/fields/Slider/Slider.spec.tsx +73 -0
  605. package/src/fields/Switch/Switch.spec.tsx +65 -0
  606. package/src/fields/TableMultiSelect.tsx +1 -0
  607. package/src/fields/TextEditor/TextEditor.spec.tsx +2 -3
  608. package/src/fields/TextEditor/TextEditor.stories.tsx +31 -1
  609. package/src/fields/ToggleGroup/ToggleGroup.spec.tsx +110 -0
  610. package/src/formEngine/formActions.ts +2 -0
  611. package/src/frappeUsers.ts +1 -0
  612. package/src/frappeViews.designLaw.spec.ts +11 -7
  613. package/src/index.ts +13 -0
  614. package/src/schemaForm/index.tsx +6 -7
  615. package/src/shared/devWarn.ts +42 -0
  616. package/src/useFrappeAggregate.ts +19 -11
  617. package/src/useFrappeFacets.ts +17 -10
  618. package/src/useFrappeRows.spec.tsx +176 -0
  619. package/src/useFrappeRows.ts +293 -0
  620. package/types/FrappeAssignment.d.ts.map +1 -1
  621. package/types/FrappeCalendar.d.ts.map +1 -1
  622. package/types/FrappeChartCard.d.ts.map +1 -1
  623. package/types/FrappeDashboard.d.ts.map +1 -1
  624. package/types/FrappeForm.d.ts +6 -2
  625. package/types/FrappeForm.d.ts.map +1 -1
  626. package/types/FrappeGantt.d.ts.map +1 -1
  627. package/types/FrappeImageView.d.ts.map +1 -1
  628. package/types/FrappeKPICard.d.ts +9 -1
  629. package/types/FrappeKPICard.d.ts.map +1 -1
  630. package/types/FrappeKanban.d.ts.map +1 -1
  631. package/types/FrappeLikedBy.d.ts.map +1 -1
  632. package/types/FrappeList.d.ts.map +1 -1
  633. package/types/FrappeListView.d.ts.map +1 -1
  634. package/types/FrappeProvider.d.ts +21 -7
  635. package/types/FrappeProvider.d.ts.map +1 -1
  636. package/types/FrappeReportBuilder.d.ts.map +1 -1
  637. package/types/FrappeReportView.d.ts.map +1 -1
  638. package/types/FrappeTable.d.ts +20 -1
  639. package/types/FrappeTable.d.ts.map +1 -1
  640. package/types/FrappeTreeView.d.ts +38 -1
  641. package/types/FrappeTreeView.d.ts.map +1 -1
  642. package/types/components/attachments.d.ts.map +1 -1
  643. package/types/components/tags.d.ts.map +1 -1
  644. package/types/components/timeline.d.ts.map +1 -1
  645. package/types/desk/DeskFormSidebar.d.ts.map +1 -1
  646. package/types/desk/DeskShell.d.ts.map +1 -1
  647. package/types/desk/DeskSidebar.d.ts.map +1 -1
  648. package/types/desk/awesomebar.d.ts.map +1 -1
  649. package/types/fieldRegistry.d.ts.map +1 -1
  650. package/types/fields/FileUpload.d.ts.map +1 -1
  651. package/types/fields/Link.d.ts.map +1 -1
  652. package/types/fields/LinkTree.d.ts.map +1 -1
  653. package/types/fields/MentionInput/index.d.ts.map +1 -1
  654. package/types/fields/Password/index.d.ts +1 -1
  655. package/types/fields/Password/index.d.ts.map +1 -1
  656. package/types/fields/TableMultiSelect.d.ts.map +1 -1
  657. package/types/formEngine/formActions.d.ts +2 -0
  658. package/types/formEngine/formActions.d.ts.map +1 -1
  659. package/types/frappeUsers.d.ts.map +1 -1
  660. package/types/index.d.ts +1 -0
  661. package/types/index.d.ts.map +1 -1
  662. package/types/schemaForm/index.d.ts.map +1 -1
  663. package/types/shared/devWarn.d.ts +23 -0
  664. package/types/shared/devWarn.d.ts.map +1 -0
  665. package/types/useFrappeAggregate.d.ts +4 -1
  666. package/types/useFrappeAggregate.d.ts.map +1 -1
  667. package/types/useFrappeFacets.d.ts +2 -1
  668. package/types/useFrappeFacets.d.ts.map +1 -1
  669. package/types/useFrappeRows.d.ts +186 -0
  670. package/types/useFrappeRows.d.ts.map +1 -0
@@ -60,6 +60,7 @@ export function DeskFormSidebar({ doctype, name }: DeskFormSidebarProps) {
60
60
  socketBaseURL: config.socketBaseURL,
61
61
  auth: config.auth,
62
62
  syncOptions: config.syncOptions,
63
+ realtime: config.realtime,
63
64
  fixtures: config.fixtures,
64
65
  }
65
66
  : undefined,
@@ -209,6 +209,7 @@ export function DeskShell({
209
209
  {showSidebar && !isNarrow && (
210
210
  <YStack
211
211
  role="navigation"
212
+ aria-label={t("Desk navigation")}
212
213
  id="desk-sidebar"
213
214
  flexShrink={0}
214
215
  data-testid="desk-sidebar-rail"
@@ -234,6 +235,7 @@ export function DeskShell({
234
235
  />
235
236
  <YStack
236
237
  role="navigation"
238
+ aria-label={t("Desk navigation")}
237
239
  id="desk-sidebar"
238
240
  position="absolute"
239
241
  top={0}
@@ -126,7 +126,12 @@ export function DeskSidebar({ onNavigate, activePath, basePath = "/desk" }: Desk
126
126
  const frappeConfig = useMemo<FrappeConnectionConfig | undefined>(
127
127
  () =>
128
128
  config
129
- ? { baseURL: config.baseURL, socketPort: config.socketPort, auth: config.auth }
129
+ ? {
130
+ baseURL: config.baseURL,
131
+ realtime: config.realtime,
132
+ socketPort: config.socketPort,
133
+ auth: config.auth,
134
+ }
130
135
  : undefined,
131
136
  [config],
132
137
  );
@@ -101,7 +101,10 @@ async function addRecentSearch(query: string): Promise<void> {
101
101
  // Helpers
102
102
  // ---------------------------------------------------------------------------
103
103
 
104
- function createHttpClientFromConfig(config: FrappeConnectionConfig): HttpClient {
104
+ function createHttpClientFromConfig(config: {
105
+ baseURL: string;
106
+ auth?: FrappeConnectionConfig["auth"];
107
+ }): HttpClient {
105
108
  return new HttpClient(
106
109
  config.baseURL,
107
110
  config.auth as Parameters<typeof HttpClient.prototype.updateAuth>[0],
@@ -145,7 +148,12 @@ export function Awesomebar({ onNavigate, basePath = "/desk", ...stackProps }: Aw
145
148
  const frappeConfig = useMemo<FrappeConnectionConfig | undefined>(
146
149
  () =>
147
150
  config
148
- ? { baseURL: config.baseURL, socketPort: config.socketPort, auth: config.auth }
151
+ ? {
152
+ baseURL: config.baseURL,
153
+ realtime: config.realtime,
154
+ socketPort: config.socketPort,
155
+ auth: config.auth,
156
+ }
149
157
  : undefined,
150
158
  [config],
151
159
  );
@@ -163,7 +171,7 @@ export function Awesomebar({ onNavigate, basePath = "/desk", ...stackProps }: Aw
163
171
  // HttpClient ref for document search
164
172
  const httpRef = useRef<HttpClient | undefined>(undefined);
165
173
  const configKeyRef = useRef("");
166
- if (config) {
174
+ if (config?.baseURL) {
167
175
  const key = `${config.baseURL}:${config.auth?.token ?? ""}`;
168
176
  if (key !== configKeyRef.current) {
169
177
  httpRef.current = createHttpClientFromConfig({
@@ -1254,6 +1254,7 @@ function TableAdapter(props: FieldRenderProps) {
1254
1254
  socketBaseURL: config.socketBaseURL,
1255
1255
  auth: config.auth,
1256
1256
  syncOptions: config.syncOptions,
1257
+ realtime: config.realtime,
1257
1258
  fixtures: config.fixtures,
1258
1259
  }
1259
1260
  : undefined;
@@ -29,12 +29,10 @@ function readCodeEditorSource() {
29
29
  return readFileSync(join(codeEditorDir(), "index.tsx"), "utf8");
30
30
  }
31
31
 
32
- function readCodeEditorStories() {
33
- return readFileSync(join(codeEditorDir(), "CodeEditor.stories.tsx"), "utf8");
34
- }
35
-
36
32
  afterEach(cleanup);
37
33
 
34
+ vi.mock("@multiplatform.one/storybook", () => ({ action: () => vi.fn() }));
35
+
38
36
  describe("frappeCodeLanguage (stock ControlCode language_map)", () => {
39
37
  it("maps stock Frappe options case-insensitively", () => {
40
38
  expect(frappeCodeLanguage("Python")).toBe("python");
@@ -102,11 +100,14 @@ describe("CodeEditorField (standalone)", () => {
102
100
  expect(result.getTextArea()).toBeNull();
103
101
  });
104
102
 
105
- it("ships CSF3 story objects so native gallery keeps args (KS blank-pane)", () => {
106
- const stories = readCodeEditorStories();
107
- expect(stories).toMatch(/export const Main = \{/);
108
- expect(stories).not.toMatch(/Main\.args\s*=/);
109
- expect(stories).toContain("value: PYTHON_FIXTURE");
103
+ it("ships CSF3 story objects so native gallery keeps args (KS blank-pane)", async () => {
104
+ const { Main, Json, ReadOnly } = await import("./CodeEditor.stories");
105
+ for (const story of [Main, Json, ReadOnly]) {
106
+ expect(typeof story).toBe("object");
107
+ expect(story.render).toBeTypeOf("function");
108
+ expect(story.args.value?.trim().length).toBeGreaterThan(0);
109
+ }
110
+ expect(ReadOnly.args.readOnly).toBe(true);
110
111
  });
111
112
 
112
113
  it("forwards knob containerRadius onto the source textarea (F14)", () => {
@@ -168,6 +168,14 @@ async function pressText(root: ParentNode, text: string) {
168
168
  });
169
169
  }
170
170
 
171
+ async function selectPeriod(period: "AM" | "PM") {
172
+ const wheel = document.querySelector('[role="slider"][aria-label="AM/PM"]');
173
+ expect(wheel).toBeTruthy();
174
+ await act(async () => {
175
+ fireEvent.keyDown(wheel!, { key: period === "AM" ? "Home" : "End" });
176
+ });
177
+ }
178
+
171
179
  beforeEach(() => {
172
180
  // Both halves portal their surfaces, so a previous case's chrome would
173
181
  // otherwise still be in the document when the next one queries it.
@@ -194,7 +202,7 @@ describe("web Date field — type=date keeps the calendar", () => {
194
202
  await openPanel(triggerInput(result.container)!);
195
203
  expect(panelText()).toContain("Su");
196
204
  // A date-only control offers no clock.
197
- expect(panelText()).not.toMatch(/\bHour\b/);
205
+ expect(document.querySelector('[role="slider"][aria-label="Hour"]')).toBeNull();
198
206
 
199
207
  await waitFor(() => expect(dayCell(15)).toBeTruthy(), { timeout: 30_000 });
200
208
  await act(async () => {
@@ -226,8 +234,8 @@ describe("web Date field — type=time renders a time control", () => {
226
234
  );
227
235
  await openPanel(triggerInput(result.container)!);
228
236
  const text = panelText();
229
- expect(text).toContain("Hour");
230
- expect(text).toContain("Min");
237
+ expect(document.querySelector('[role="slider"][aria-label="Hour"]')).toBeTruthy();
238
+ expect(document.querySelector('[role="slider"][aria-label="Min"]')).toBeTruthy();
231
239
  expect(text).not.toContain("Su");
232
240
  });
233
241
 
@@ -239,11 +247,11 @@ describe("web Date field — type=time renders a time control", () => {
239
247
  );
240
248
  await openPanel(triggerInput(result.container)!);
241
249
  // 9:00 AM → PM is a deterministic edit with no wheel animation in it.
242
- await pressText(document.body, "PM");
250
+ await selectPeriod("PM");
243
251
 
244
252
  // The control speaks `HH:mm`; the field re-serializes through the shared
245
253
  // wire body, so what persists carries seconds like every other writer.
246
- expect(onChange).toHaveBeenCalledWith("21:00:00");
254
+ await waitFor(() => expect(onChange).toHaveBeenCalledWith("21:00:00"));
247
255
  });
248
256
 
249
257
  it("adopts a seconds-less HH:mm value too (what Frappe hands a fresh field)", async () => {
@@ -292,7 +300,9 @@ describe("web Date field — type=datetime renders date AND time", () => {
292
300
  await openPanel(triggerInput(result.container)!);
293
301
  expect(panelText()).toContain("Su");
294
302
  await pressText(document.body, "Time");
295
- await waitFor(() => expect(panelText()).toContain("Hour"), { timeout: 30_000 });
303
+ await waitFor(() =>
304
+ expect(document.querySelector('[role="slider"][aria-label="Hour"]')).toBeTruthy(),
305
+ );
296
306
  });
297
307
 
298
308
  it("a day change keeps the existing time — and the picker, not the serializer, keeps it", async () => {
@@ -330,8 +340,8 @@ describe("web Date field — type=datetime renders date AND time", () => {
330
340
  await pressText(document.body, "Time");
331
341
  // 2:30 PM → AM. Carrying `previousValue` here would have pinned the old
332
342
  // 14:30 back over the edit the user just made.
333
- await pressText(document.body, "AM");
334
- expect(onChange).toHaveBeenLastCalledWith("2026-03-05 02:30:00");
343
+ await selectPeriod("AM");
344
+ await waitFor(() => expect(onChange).toHaveBeenLastCalledWith("2026-03-05 02:30:00"));
335
345
  });
336
346
  });
337
347
 
@@ -412,7 +422,7 @@ describe("web and native persist byte-identical wire strings", () => {
412
422
 
413
423
  it("time — moving 9:00 AM to 9:00 PM writes the same string on both halves", async () => {
414
424
  const web = await webPick("time", "09:00:00", async () => {
415
- await pressText(document.body, "PM");
425
+ await selectPeriod("PM");
416
426
  });
417
427
  cleanup();
418
428
  mockState.picks.length = 0;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Duration adapter contract specs. The Frappe Duration field is seconds in,
3
+ * seconds out; this file only pins that the hop to forms Duration keeps
4
+ * value / onChange / disabled / label / error. The segment math lives in
5
+ * the forms spec.
6
+ */
7
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
8
+ import { cleanup, fireEvent } from "@testing-library/react";
9
+ import type React from "react";
10
+ import { afterEach, describe, expect, it, vi } from "vitest";
11
+ import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
12
+ import { Duration } from ".";
13
+
14
+ afterEach(cleanup);
15
+
16
+ const hours = (container: HTMLElement) =>
17
+ container.querySelector('input[aria-label="Hours"]') as HTMLInputElement | null;
18
+
19
+ describe("Duration composes the forms Duration", () => {
20
+ it("paints a controlled seconds value into the hours segment", () => {
21
+ const result = renderWithProviders(<Duration label="Time" value={7200} onChange={() => {}} />);
22
+ expect(hours(result.container)?.value ?? hours(result.container)?.getAttribute("value")).toBe(
23
+ "2",
24
+ );
25
+ });
26
+
27
+ it("emits seconds through canonical onChange", () => {
28
+ const onChange = vi.fn();
29
+ const result = renderWithProviders(<Duration label="Time" value={3600} onChange={onChange} />);
30
+ fireEvent.keyDown(hours(result.container) as HTMLInputElement, { key: "ArrowUp" });
31
+ expect(onChange).toHaveBeenCalledWith(7200);
32
+ });
33
+
34
+ it("forwards disabled onto the hours segment", () => {
35
+ const result = renderWithProviders(
36
+ <Duration label="Time" value={3600} disabled onChange={() => {}} />,
37
+ );
38
+ const el = hours(result.container);
39
+ expect(el?.getAttribute("aria-disabled") === "true" || el?.disabled).toBe(true);
40
+ });
41
+
42
+ it("forwards readOnly onto the hours segment", () => {
43
+ const result = renderWithProviders(
44
+ <Duration label="Time" value={3600} readOnly onChange={() => {}} />,
45
+ );
46
+ const el = result.container.querySelector("input");
47
+ expect(el?.getAttribute("aria-readonly") === "true" || el?.readOnly).toBe(true);
48
+ });
49
+
50
+ it("shows the label and error", () => {
51
+ const result = renderWithProviders(
52
+ <Duration label="Time" value={3600} error="not a duration" onChange={() => {}} />,
53
+ );
54
+ expect(result.container.textContent).toContain("Time");
55
+ expect(result.container.textContent).toContain("not a duration");
56
+ });
57
+ });
58
+
59
+ describe("registry resolution (Duration fieldtype)", () => {
60
+ function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
61
+ return { value: "", onChange: () => {}, ...overrides };
62
+ }
63
+
64
+ it("resolves 'Duration' to the Duration adapter and coerces a non-number to 0", () => {
65
+ const Component = getFieldComponent("Duration")!;
66
+ const element = (Component as Function)(
67
+ propsFor({ value: "nope", label: "Time" }),
68
+ ) as React.ReactElement<Record<string, unknown>>;
69
+ expect(element.type).toBe(Duration);
70
+ expect(element.props.value).toBe(0);
71
+ expect(element.props.label).toBe("Time");
72
+ });
73
+ });
@@ -132,6 +132,7 @@ export function FileUpload({
132
132
  socketBaseURL: config?.socketBaseURL,
133
133
  auth: auth ?? config?.auth,
134
134
  syncOptions: config?.syncOptions,
135
+ realtime: config?.realtime,
135
136
  fixtures: config?.fixtures,
136
137
  }
137
138
  : undefined;
@@ -73,7 +73,12 @@ function useLinkConnection(baseURL?: string, auth?: LinkProps["auth"]) {
73
73
  const config = useFrappeConfig();
74
74
  const finalBaseURL = baseURL ?? config?.baseURL ?? "";
75
75
  const connectionConfig: FrappeConnectionConfig | undefined = finalBaseURL
76
- ? { baseURL: finalBaseURL, socketPort: config?.socketPort, auth: auth ?? config?.auth }
76
+ ? {
77
+ baseURL: finalBaseURL,
78
+ realtime: config?.realtime,
79
+ socketPort: config?.socketPort,
80
+ auth: auth ?? config?.auth,
81
+ }
77
82
  : undefined;
78
83
  return { config, connectionConfig };
79
84
  }
@@ -53,10 +53,11 @@ export function LinkTree({
53
53
  baseURL: finalBaseURL,
54
54
  socketPort: config?.socketPort,
55
55
  auth: finalAuth,
56
+ realtime: config?.realtime,
56
57
  fixtures: config?.fixtures,
57
58
  }
58
59
  : undefined,
59
- [finalBaseURL, config?.socketPort, finalAuth, config?.fixtures],
60
+ [finalBaseURL, config?.socketPort, config?.realtime, finalAuth, config?.fixtures],
60
61
  );
61
62
 
62
63
  const { meta } = useDocTypeMeta(connectionConfig, doctype);
@@ -0,0 +1,110 @@
1
+ /**
2
+ * MentionInputField contract specs. The registry hands `value` and `onChange`
3
+ * straight to this adapter (MentionAdapter in fieldRegistry). The failure
4
+ * mode of a thin adapter is dropping those two, so a saved comment never
5
+ * paints and a typed comment never emits (LC-14). Pin the hop.
6
+ */
7
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
8
+ import { act, cleanup, fireEvent } from "@testing-library/react";
9
+ import type React from "react";
10
+ import { afterEach, describe, expect, it, vi } from "vitest";
11
+ import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
12
+ import { MentionInputField, type MentionValue } from ".";
13
+
14
+ afterEach(cleanup);
15
+
16
+ const mentions = [{ trigger: "@", data: [{ id: "u1", display: "Ada" }] }];
17
+
18
+ const seeded: MentionValue = { text: "hello ada", mentions: [] };
19
+
20
+ const textarea = (container: HTMLElement) =>
21
+ container.querySelector("textarea") as HTMLTextAreaElement | null;
22
+
23
+ describe("MentionInputField composes the forms MentionInput", () => {
24
+ it("paints a controlled value onto the textarea", () => {
25
+ const result = renderWithProviders(
26
+ <MentionInputField label="Comment" mentions={mentions} value={seeded} onChange={() => {}} />,
27
+ );
28
+ expect(textarea(result.container)?.value).toBe("hello ada");
29
+ });
30
+
31
+ it("emits a MentionValue through canonical onChange", async () => {
32
+ const onChange = vi.fn();
33
+ const result = renderWithProviders(
34
+ <MentionInputField
35
+ label="Comment"
36
+ mentions={mentions}
37
+ value={{ text: "", mentions: [] }}
38
+ onChange={onChange}
39
+ />,
40
+ );
41
+ await act(async () => {
42
+ fireEvent.change(textarea(result.container) as HTMLTextAreaElement, {
43
+ target: { value: "typed" },
44
+ });
45
+ });
46
+ expect(onChange).toHaveBeenCalled();
47
+ const emitted = onChange.mock.calls.at(-1)?.[0] as MentionValue;
48
+ expect(emitted.text).toBe("typed");
49
+ expect(Array.isArray(emitted.mentions)).toBe(true);
50
+ });
51
+
52
+ it("forwards disabled onto the textarea", () => {
53
+ const result = renderWithProviders(
54
+ <MentionInputField
55
+ label="Comment"
56
+ mentions={mentions}
57
+ value={seeded}
58
+ disabled
59
+ onChange={() => {}}
60
+ />,
61
+ );
62
+ const el = textarea(result.container);
63
+ expect(el?.disabled || el?.getAttribute("aria-disabled") === "true").toBe(true);
64
+ });
65
+
66
+ it("forwards readOnly onto the textarea", () => {
67
+ const result = renderWithProviders(
68
+ <MentionInputField
69
+ label="Comment"
70
+ mentions={mentions}
71
+ value={seeded}
72
+ readOnly
73
+ onChange={() => {}}
74
+ />,
75
+ );
76
+ const el = textarea(result.container);
77
+ expect(el?.readOnly || el?.getAttribute("aria-readonly") === "true").toBe(true);
78
+ });
79
+
80
+ it("shows the label and error", () => {
81
+ const result = renderWithProviders(
82
+ <MentionInputField
83
+ label="Comment"
84
+ mentions={mentions}
85
+ value={seeded}
86
+ error="too short"
87
+ onChange={() => {}}
88
+ />,
89
+ );
90
+ expect(result.container.textContent).toContain("Comment");
91
+ expect(result.container.textContent).toContain("too short");
92
+ });
93
+ });
94
+
95
+ describe("registry resolution (Mention fieldtype)", () => {
96
+ function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
97
+ return { value: "", onChange: () => {}, ...overrides };
98
+ }
99
+
100
+ it("resolves 'Mention' to MentionInputField and hands value through", () => {
101
+ const Component = getFieldComponent("Mention")!;
102
+ expect(Component).toBeTruthy();
103
+ const element = (Component as Function)(
104
+ propsFor({ value: "hello ada", label: "Comment" }),
105
+ ) as React.ReactElement<Record<string, unknown>>;
106
+ expect(element.type).toBe(MentionInputField);
107
+ expect(element.props.value).toBe("hello ada");
108
+ expect(element.props.label).toBe("Comment");
109
+ });
110
+ });
@@ -79,7 +79,8 @@ export function MentionInputField<
79
79
  _preserveValue,
80
80
  validators,
81
81
  disabled,
82
- _value,
82
+ value,
83
+ onChange,
83
84
  mentions,
84
85
  placeholder,
85
86
  onMentionSelect,
@@ -103,6 +104,8 @@ export function MentionInputField<
103
104
  id={fieldProps.id}
104
105
  size={fieldProps.size}
105
106
  disabled={disabled}
107
+ value={value}
108
+ onChange={onChange}
106
109
  mentions={mentions ?? []}
107
110
  placeholder={placeholder}
108
111
  onMentionSelect={onMentionSelect}
@@ -45,7 +45,7 @@ export type PasswordProps<
45
45
  unknown,
46
46
  string
47
47
  >,
48
- "children" | "field"
48
+ "children" | "field" | "onChange"
49
49
  > &
50
50
  Partial<
51
51
  Omit<
@@ -57,6 +57,15 @@ describe("ProgressField chrome", () => {
57
57
  expect(container.firstElementChild).toBeTruthy();
58
58
  expect(container.textContent).toContain("Completion");
59
59
  });
60
+
61
+ it("forwards the controlled value onto the progressbar", () => {
62
+ const { container } = renderWithProviders(
63
+ <ProgressField label="Completion" value={65} max={100} />,
64
+ );
65
+ expect(container.querySelector("[role='progressbar']")?.getAttribute("aria-valuenow")).toBe(
66
+ "65",
67
+ );
68
+ });
60
69
  });
61
70
 
62
71
  /**
@@ -0,0 +1,93 @@
1
+ /**
2
+ * RadioGroupField contract specs. The adapter maps `onChange` onto the forms
3
+ * RadioGroup's `onValueChange`. Pin that value, onChange, disabled, label
4
+ * and error survive the hop.
5
+ */
6
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
7
+ import { act, cleanup, fireEvent } from "@testing-library/react";
8
+ import type React from "react";
9
+ import { afterEach, describe, expect, it, vi } from "vitest";
10
+ import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
11
+ import { RadioGroupField } from ".";
12
+
13
+ afterEach(cleanup);
14
+
15
+ const options = [
16
+ { label: "Red", value: "red" },
17
+ { label: "Blue", value: "blue" },
18
+ ];
19
+
20
+ const radios = (container: HTMLElement) =>
21
+ Array.from(container.querySelectorAll('[role="radio"]')) as HTMLElement[];
22
+
23
+ describe("RadioGroupField composes the forms RadioGroup", () => {
24
+ it("paints a controlled value onto the matching radio", () => {
25
+ const result = renderWithProviders(
26
+ <RadioGroupField label="Color" value="blue" options={options} onChange={() => {}} />,
27
+ );
28
+ const all = radios(result.container);
29
+ const checked = all.find((el) => el.getAttribute("aria-checked") === "true");
30
+ expect(checked).toBeTruthy();
31
+ // option order is Red, Blue — the disc itself has no text
32
+ expect(checked).toBe(all[1]);
33
+ });
34
+
35
+ it("emits the option value through canonical onChange", async () => {
36
+ const onChange = vi.fn();
37
+ const result = renderWithProviders(
38
+ <RadioGroupField label="Color" value="red" options={options} onChange={onChange} />,
39
+ );
40
+ const blue = radios(result.container).find((el) => (el.textContent || "").includes("Blue"));
41
+ expect(blue || radios(result.container)[1]).toBeTruthy();
42
+ await act(async () => {
43
+ fireEvent.click(blue ?? radios(result.container)[1]);
44
+ });
45
+ expect(onChange).toHaveBeenCalledWith("blue");
46
+ });
47
+
48
+ it("forwards disabled onto the radios", () => {
49
+ const result = renderWithProviders(
50
+ <RadioGroupField label="Color" value="red" options={options} disabled onChange={() => {}} />,
51
+ );
52
+ const el = radios(result.container)[0];
53
+ expect(el?.getAttribute("aria-disabled") === "true" || el?.hasAttribute("disabled")).toBe(true);
54
+ });
55
+
56
+ it("shows the label and error", () => {
57
+ const result = renderWithProviders(
58
+ <RadioGroupField
59
+ label="Color"
60
+ value="red"
61
+ options={options}
62
+ error="pick one"
63
+ onChange={() => {}}
64
+ />,
65
+ );
66
+ expect(result.container.textContent).toContain("Color");
67
+ expect(result.container.textContent).toContain("pick one");
68
+ });
69
+ });
70
+
71
+ describe("registry resolution (Radio fieldtype)", () => {
72
+ function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
73
+ return { value: "", onChange: () => {}, ...overrides };
74
+ }
75
+
76
+ it("resolves 'Radio' to RadioGroupField and splits df.options on newlines", () => {
77
+ const Component = getFieldComponent("Radio")!;
78
+ const element = (Component as Function)(
79
+ propsFor({
80
+ value: "Red",
81
+ label: "Color",
82
+ fieldMeta: { options: "Red\nBlue" },
83
+ } as Partial<FieldRenderProps>),
84
+ ) as React.ReactElement<Record<string, unknown>>;
85
+ expect(element.type).toBe(RadioGroupField);
86
+ expect(element.props.value).toBe("Red");
87
+ expect(element.props.label).toBe("Color");
88
+ expect(element.props.options).toEqual([
89
+ { label: "Red", value: "Red" },
90
+ { label: "Blue", value: "Blue" },
91
+ ]);
92
+ });
93
+ });
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Signature adapter contract specs. The Frappe Signature field stores a
3
+ * data URL; this adapter must hand value / onChange / disabled / label /
4
+ * error to the forms Signature pad. Drawing lives in the forms spec.
5
+ */
6
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
7
+ import { cleanup, fireEvent } from "@testing-library/react";
8
+ import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
9
+ import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
10
+ import type React from "react";
11
+ import { Signature } from ".";
12
+
13
+ function encodeSignature(strokes: number[][][]): string {
14
+ const json = JSON.stringify({ v: 2, s: strokes });
15
+ return `data:application/json;base64,${btoa(json)}`;
16
+ }
17
+
18
+ const inkedValue = encodeSignature([
19
+ [
20
+ [0.1, 0.2, 0.5],
21
+ [0.4, 0.3, 0.5],
22
+ [0.7, 0.25, 0.5],
23
+ ],
24
+ ]);
25
+
26
+ function getPad(container: HTMLElement): HTMLElement {
27
+ const label = container.querySelector("label[for]") as HTMLLabelElement | null;
28
+ const id = label?.htmlFor;
29
+ const pad = id ? (container.querySelector(`#${CSS.escape(id)}`) as HTMLElement | null) : null;
30
+ if (!pad) throw new Error("signature pad not found");
31
+ return pad;
32
+ }
33
+
34
+ beforeAll(() => {
35
+ HTMLCanvasElement.prototype.getContext = vi.fn(() => ({
36
+ clearRect: vi.fn(),
37
+ beginPath: vi.fn(),
38
+ moveTo: vi.fn(),
39
+ lineTo: vi.fn(),
40
+ stroke: vi.fn(),
41
+ fillRect: vi.fn(),
42
+ drawImage: vi.fn(),
43
+ })) as unknown as typeof HTMLCanvasElement.prototype.getContext;
44
+ });
45
+
46
+ afterEach(cleanup);
47
+
48
+ describe("Signature composes the forms Signature", () => {
49
+ it("paints a controlled value as a signed pad", () => {
50
+ const result = renderWithProviders(
51
+ <Signature label="Sign here" value={inkedValue} onChange={() => {}} />,
52
+ );
53
+ expect(getPad(result.container).getAttribute("data-signed")).toBe("true");
54
+ });
55
+
56
+ it("emits an empty string through canonical onChange on Delete", () => {
57
+ const onChange = vi.fn();
58
+ const result = renderWithProviders(
59
+ <Signature label="Sign here" value={inkedValue} onChange={onChange} />,
60
+ );
61
+ const pad = getPad(result.container);
62
+ fireEvent.focus(pad);
63
+ fireEvent.keyDown(pad, { key: "Delete" });
64
+ expect(onChange).toHaveBeenCalledWith("");
65
+ });
66
+
67
+ it("forwards readOnly onto the pad", () => {
68
+ const result = renderWithProviders(
69
+ <Signature label="Sign here" value={inkedValue} readOnly onChange={() => {}} />,
70
+ );
71
+ expect(getPad(result.container).getAttribute("aria-readonly")).toBe("true");
72
+ });
73
+
74
+ it("forwards disabled onto the pad", () => {
75
+ const result = renderWithProviders(
76
+ <Signature label="Sign here" value={inkedValue} disabled onChange={() => {}} />,
77
+ );
78
+ const pad = getPad(result.container);
79
+ expect(pad.getAttribute("aria-disabled") === "true" || pad.hasAttribute("disabled")).toBe(true);
80
+ });
81
+
82
+ it("shows the label and error", () => {
83
+ const result = renderWithProviders(
84
+ <Signature label="Sign here" value="" error="signature required" onChange={() => {}} />,
85
+ );
86
+ expect(result.container.textContent).toContain("Sign here");
87
+ expect(result.container.textContent).toContain("signature required");
88
+ });
89
+ });
90
+
91
+ describe("registry resolution (Signature fieldtype)", () => {
92
+ function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
93
+ return { value: "", onChange: () => {}, ...overrides };
94
+ }
95
+
96
+ it("resolves 'Signature' to the Signature adapter and hands value through", () => {
97
+ const Component = getFieldComponent("Signature")!;
98
+ const element = (Component as Function)(
99
+ propsFor({ value: inkedValue, label: "Sign here" }),
100
+ ) as React.ReactElement<Record<string, unknown>>;
101
+ expect(element.type).toBe(Signature);
102
+ expect(element.props.value).toBe(inkedValue);
103
+ expect(element.props.label).toBe("Sign here");
104
+ });
105
+ });